mIRC Homepage
hey there.

i hope some can help here...

i know it's posible to loop and make it look throughout a file...

i need to look in the file test.txt

the test.txt has 200 lines, which i have defined in a variable like :
Code:
var %total.lines $lines(test.txt)


i now need to loop through the test.txt starting from line 1 and look through every line until i reach line 200.

line 1 : bla.bla
line 2 : he.he
line 3 : bleeeh.bleeeeh

etc etc...

then i need it to make a variable with the text from the line so i can match it.

something like:
Code:
 if (%x isin lol.look.at.him.he.he.sucks) { echo -a %x }

where %x is the text from the test.txt


hope its understandable smile

regards.
Code:
alias find {
  var %f = test.txt, %l = $lines(%f)
  while (%l) {
    var %x = lol|look|at|him|he|sucks
    if ($regex($read(%f,n,%l),/( $+ %x $+ )/i)) {
      echo -a * I've found one match for: $regml(1)
    }
    dec %l
  }
}
Enter /find to search the matches listed in the regex against the test.txt.

I assume your intention is to find matches in test.txt against what people say in the channel. If that's the case, you can use:
Code:
on *:text:*:#: find $1-
on *:action:*:#: find $1-
on *:notice:*:#: find $1-
alias -l find {
  var %f = test.txt, %l = $lines(%f)
  while (%l) {
    if ($regex($1-,/\b( $+ $read(%f,n,%l) $+ )\b/iS)) {
      ;your command here
    }
    dec %l
  }
}
Your loop is very inefficient, $read itself has some functions to compare a string against each line of a file, wildcard or regex are supported.
Originally Posted By: Wims
Your loop is very inefficient
You should point out the inefficiency that you think my example should be improved upon. It's a polite gesture to explain without dropping a line in an in-your-face manner.

I know there are -r, -s and -w switches, but a loop is required or it will only return one result. I was borrowing the regex engine to match strings in the test.txt.
EDIT: This was meant as a reply to the OP.

If you really need every line's information, $fread is probably going to be the most efficient. If you want to search for a given text in the file, then $read() with -r,-s,-w options is probably the best for a single match (as would be the case for most spam/language catchers), or for multiple matches with a search text, /filter is probably the best option.

With more details on what the script is meant to do, the best option could be given. But, a real basic script if you don't want to learn anything beyond $read() would be...

Code:
alias ReadFile {
  var %counter = 1, %total = $lines(file)
  while (%counter <= %total) { 
    var %line = $read(file,%counter)
    ; Do whatever you want with %line here (such as the following echo command)
    echo -a %line
    inc %counter
  }
}


Replace the two instances of "file" with the filename (and path if it's located somewhere other than $mircdir).

Use: /readfile

Again, there are better options, but this is about as basic as you can get.

Here's a basic spam/language check...

Code:
on *:text:*:#: {
  var %counter = 1, %total = $0
  while (%counter <= %total) {
    if ($read(file,w,$+(*,$($+($chr(36),%counter),2),*))) { echo -a spam/language found... | break }
    inc %counter
  }
}


The file can then be set up as:
badword1
badword2
badword3
etc...

Of course, such a filter wouldn't just echo something. You'd usually kick/ban the person or something along those lines. This is just a really basic example.
I can do it like so:
Code:
 var %x 1
  while $read(file,n,%x) {
    if $regex($1-,/\b(\Q $+ $replacecs($v1,\E,\E\\E\Q,$chr(32),\E|\Q) $+ \E)\b/iS) {
      ;cmd
    }
    inc %x
  }
Sorry, the way you used $read is the bad thing, even if we do need the loop for multiple matches when using $read, it should never be used this way (getting each line and match with and if statement), look at this exemple.
Using this file ($mircdirtest.txt) :
Quote:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbb
ccccccccccccccccccccccccccccc
ddddddddddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeeeeeeeeeee
fffffffffffffffffffffffffffff
ggggggggggggggggggggggggggggg
hhhhhhhhhhhhhhhhhhhhhhhhhhhhh
iiiiiiiiiiiiiiiiiiiiiiiiiiiii
jjjjjjjjjjjjjjjjjjjjjjjjjjjjj
kkkkkkkkkkkkkkkkkkkkkkkkkkkkk
lllllllllllllllllllllllllllll
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
mmmmmmmmmmmmmmmmmmmmmmmmmmmmm
nnnnnnnnnnnnnnnnnnnnnnnnnnnnn
ooooooooooooooooooooooooooooo
ppppppppppppppppppppppppppppp
qqqqqqqqqqqqqqqqqqqqqqqqqqqqq
rrrrrrrrrrrrrrrrrrrrrrrrrrrrr
sssssssssssssssssssssssssssss
ttttttttttttttttttttttttttttt
uuuuuuuuuuuuuuuuuuuuuuuuuuuuu
vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
wwwwwwwwwwwwwwwwwwwwwwwwwwwww
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
yyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzz
{{{{{{{{{{{{{{{{{{{{{{{{{{{{{
|||||||||||||||||||||||||||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
And this code :
Code:
alias benchread {
  var %t $ticks ,%a 1000,%l $lines(test.txt)
  while (%a) { 
    var %b 1 
    while (%b <= %l) { 
      if (*}}}}}}}}}}* iswm $read(test.txt,n,%b)) noop match the file on line %b : $v1 
      ; if ($regex($read(test.txt,n,%b),/\Q}}}}}}}}}}\E/i) noop match the file on line %b : $v1 
      inc %b
    }
    dec %a
  } 
  echo -a in $calc($ticks - %t) ms
}

alias benchread1 {
  var %t $ticks ,%a 1000
  while (%a) {
    var %l 1
    while ($read(test.txt, wn, *}}}}}}}}}}*,%l) != $null) {
      noop match the file on line $readn : $v1 
      %l = $readn + 1
    }
    ;  while ($read(test.txt, rn, /}}}}}}}}}}/i,%l) != $null) { noop match the file on line $readn : $v1 | %l = $readn +1 }
    dec %a
  } 
  echo -a in $calc($ticks - %t) ms
}
I get :
Originally Posted By: benchread
in 6178 ms
in 6209 ms
in 6177 ms
Originally Posted By: benchread1
in 951 ms
in 921 ms
in 936 ms
for wildcard match and
Quote:
in 6895 ms
in 6896 ms
in 6896 ms
-
in 1045 ms
in 1092 ms
in 1060 ms
for regex, as you can see using $read with the s or w switch and the N feature, that start searching at the Nth line of the file is far better

edit : this is just an exemple, of course /filter is better than a loop if multiple matches are to be done.
Well, I thank you for your effort, Wims. I'll bear that in mind. :-)
Even faster:

Code:
alias _test { noop $1- }
alias benchread1 { 
  var %ticks = $ticks
  filter -fk test.txt _test *}}}}}}}}}}* 
  echo -a * Test completed in: $calc($ticks - %ticks) ms with $filtered results.
}
thanks for all the answers,

what i exactly have is a csv file with text like :

Quote:

prison.break;scripted;us
csi.miami;scripted;us
the.mentalist;scripted;us

so there will be no lines that has same text...

i tried the alias readfile, but that makes my mirc stall and all i can do is close it from task manager...

if af ilter is the best / fastes way to go , i'd like that indeed .
Taken from hixxy's filter suggestion, here is it:
Code:
alias _test {
  var %x = lol.look.at.him.he.he.sucks
  if ($isfile(test.txt)) && ($isid) { echo -a * Match Found: $1- }
  else { filter -fk test.txt _test $+(*,%x,*)) }
}

Originally Posted By: hixxy
Even faster:

Code:
alias _test { noop $1- }
alias benchread1 { 
  var %ticks = $ticks
  filter -fk test.txt _test *}}}}}}}}}}* 
  echo -a * Test completed in: $calc($ticks - %ticks) ms with $filtered results.
}


that still requires mIRC to evaluate $_test($1-) for $1- = each line in turn :P

knowing that mIRC evaluates $<arg>($1-) where <arg> is the argument you've supplied, necessarily a single word, we can start throwing out suggestions as to what value of <arg> we can select that takes the least amount of work to evaluate.

for a while i would've suggested <arg> = () which causes mIRC to evaluate $()($1-) for each matching line. $() produces $null of course, and the bit on the end is simply ignored to save mIRC the trouble of evaluating $1-.

however, after a bit testing, it seems <arg> = ~~ (producing $~~($1-) as the piece of code to evaluate repeatedly) is slightly quicker. $~identifier(), as we know, avoids calling custom aliases and also suppresses the identifier warning if 'identifier' doesn't exist as an internal identifier. generally, $abc won't be evaluated if $~ident($abc) is used and 'ident' doesn't exist, so like before we avoid $1- having to be evaluated.

i dare say $~~() is unlikely to ever be introduced as an internal identifier, and for some reason mIRC seems to be able to recognize that $~~() doesn't exist slightly quicker than, for example, $~a() or $~b() etc.
Originally Posted By: Tomao
Taken from hixxy's filter suggestion, here is it:
Code:
alias _test {
  var %x = lol.look.at.him.he.he.sucks
  if ($isfile(test.txt)) && ($isid) { echo -a * Match Found: $1- }
  else { filter -fk test.txt _test $+(*,%x,*)) }
}



i can't get this to work. it aint echo'in anything. however if i use var %x he.he it finds it, but when he.he is used in a sentence, it returns $null


i have in my file e.g :
UEFA.CHAMPIONS.LEAGUE;SPORTS;SOCCER

and i need to be able to do a /test UEFA.CHAMPIONS.LEAGUE.2010.2011 and have it crosscheck the test.txt file for uefa.champions.league only. however 2010.2011 could be random text in the same word...
as far as i can see all the replies work the other way around...

i have text in the txt file like

prison.break;scripted;us
the.mentalist;scripted;us
uefa.champions.league;sports;n/a

and then my trigger (lets call it %y) is like:
var %y uefa.champions.league.2010.2011.arsenal.vs.barcelona

or

var %y uefa.champions.league.highlights

then i need it to set %x as uefa.champions.league and
if (%x isin %y) { echo -a * MATCH FOUND %x matches %y }

Nice smile

The /filter method (both mine and yours) yields search times of 0ms for me on Wims' test file every time I run it, can't get much faster laugh (yes I know that is because of the inaccuracy of $ticks but still :p)
Yeah I know filter is faster, I was just showing how $read should be used, for exemple if you only want N matches, filter could be slower than using $read on a big file in that case
In theory /filter will be faster for more than one match, $read will be faster for only one match.

$read opens a file handle, reads from the start to the position in the file which matches the line number/search parameters you specify, then closes the file handle.

/filter opens a file handle, reads from the start to the end of the file, matching the contents as it goes, then closes the file handle.

If you call $read more than once, it opens the file handle, reads from the start of the file and then closes it each time -- all of which are overheads that /filter doesn't have.

Multiple $reads could potentially be faster if the matches are found near the start of the file, as it will have less data to go through than /filter.

In any event, was just offering another alternative smile
You two seem to have lost track of this thread so far. :p
I agree about the theory and with what you said about $read and filter
Quote:
Multiple $reads could potentially be faster if the matches are found near the start of the file, as it will have less data to go through than /filter.
I made another test to check that :

%n is the number of match we want from the start of the file (just some copy/paste of the previous file) :
Code:
alias benchread1 {
  var %t $ticks ,%a 1000
  while (%a) {
    var %l 1,%n 2
    while ($read(test.txt, wn, *}}}}}}}}}}*,%l) != $null) && (%n) { noop match the file on line $readn : $v1 | %l = $readn + 1 | dec %n }
    dec %a
  } 
  echo -a in $calc($ticks - %t) ms
}

alias _test if (%n) noop match the file on line $1 : $2- | dec %n
alias benchread2 { 
  var %t $ticks,%a 1000
  while (%a) {
    set -u %n 2
    filter -fnk test.txt _test *}}}}}}}}}}*
    dec %a 
  } 
  echo -a in $calc($ticks - %t) ms
}
Using this file, /filter is slower than $read for %n <= 4 in my test

Quote:
In any event, was just offering another alternative
Yeah, it's fine, but the purpose of my post was to compare two methods involving $read, not to do the job the fastest ways possible





Really? Filter beats $read every time for me. I've slightly adjusted your benchmark aliases so that it tells you which method it's benchmarking in the echo.

I've also added a /benchtest command to run each bench 10 times.

Code:
alias benchread1 {
  var %t $ticks ,%a 1000
  while (%a) {
    var %l 1,%n 2
    while ($read(test.txt, wn, *}}}}}}}}}}*,%l) != $null) && (%n) { noop match the file on line $readn : $v1 | %l = $readn + 1 | dec %n }
    dec %a
  } 
  echo -a in $calc($ticks - %t) ms ($read)
}

alias _test if (%n) noop match the file on line $1 : $2- | dec %n
alias benchread2 { 
  var %t $ticks,%a 1000
  while (%a) {
    set -u %n 2
    filter -fnk test.txt _test *}}}}}}}}}}*
    dec %a 
  } 
  echo -a in $calc($ticks - %t) ms (/filter)
}
alias benchtest { 
  var %i = 10
  while (%i) { 
    benchread1
    benchread2
    if (%i > 1) { linesep -a }
    dec %i
  }
}


Here's my results for %n = 2:

Quote:
in 1344 ms ($read)
in 562 ms (/filter)
-
in 1344 ms ($read)
in 578 ms (/filter)
-
in 1359 ms ($read)
in 578 ms (/filter)
-
in 1375 ms ($read)
in 563 ms (/filter)
-
in 1359 ms ($read)
in 578 ms (/filter)
-
in 1344 ms ($read)
in 578 ms (/filter)
-
in 1359 ms ($read)
in 579 ms (/filter)
-
in 1343 ms ($read)
in 578 ms (/filter)
-
in 1344 ms ($read)
in 578 ms (/filter)
-
in 1344 ms ($read)
in 578 ms (/filter)


And with %n = 1:

Quote:
in 844 ms ($read)
in 578 ms (/filter)
-
in 859 ms ($read)
in 563 ms (/filter)
-
in 843 ms ($read)
in 578 ms (/filter)
-
in 844 ms ($read)
in 563 ms (/filter)
-
in 843 ms ($read)
in 579 ms (/filter)
-
in 843 ms ($read)
in 563 ms (/filter)
-
in 844 ms ($read)
in 562 ms (/filter)
-
in 844 ms ($read)
in 562 ms (/filter)
-
in 844 ms ($read)
in 563 ms (/filter)
-
in 843 ms ($read)
in 578 ms (/filter)
Did you update the file ?

I Changed %i to 4 smile
Originally Posted By: n=2
in 967 ms ($read)
in 2184 ms (/filter)
-
in 951 ms ($read)
in 2200 ms (/filter)
-
in 967 ms ($read)
in 2184 ms (/filter)
-
in 967 ms ($read)
in 2200 ms (/filter)
Originally Posted By: n=3
in 1529 ms ($read)
in 2184 ms (/filter)
-
in 1467 ms ($read)
in 2199 ms (/filter)
-
in 1467 ms ($read)
in 2199 ms (/filter)
-
in 1466 ms ($read)
in 2200 ms (/filter)
Originally Posted By: n=4
in 2106 ms ($read)
in 2199 ms (/filter)
-
in 2044 ms ($read)
in 2184 ms (/filter)
-
in 2059 ms ($read)
in 2199 ms (/filter)
-
in 2060 ms ($read)
in 2199 ms (/filter)
Originally Posted By: n=5
in 2777 ms ($read)
in 2200 ms (/filter)
-
in 2745 ms ($read)
in 2200 ms (/filter)
-
in 2730 ms ($read)
in 2215 ms (/filter)
-
in 2761 ms ($read)
in 2216 ms (/filter)
I get the same results as you with the old file.
I see two guys try to beat down on one another...with a proud smile brimming with competitiveness. lol
I was just curious about $read being slower everytime so I benchmarked it. No proud smile here, we're just talking about the results wink (and he should have the same as me, I hope he didn't update the file)

edit : just noticed
Quote:
if (%i > 1) { linesep -a }
-a deosn't exist afaik, what does it do ? -s does but isn't documented.
not at all, they seem to be entirely well spirited :P investigation and discussion, even if slightly tangential, is something that used to happen much more often on this board.
I can easily see the -a being a typo for -s
Originally Posted By: explodedk
as far as i can see all the replies work the other way around...

i have text in the txt file like

prison.break;scripted;us
the.mentalist;scripted;us
uefa.champions.league;sports;n/a

and then my trigger (lets call it %y) is like:
var %y uefa.champions.league.2010.2011.arsenal.vs.barcelona

or

var %y uefa.champions.league.highlights

then i need it to set %x as uefa.champions.league and
if (%x isin %y) { echo -a * MATCH FOUND %x matches %y }



i still need answer to my question guys... smile
Yeah you're right, I didn't realise you'd posted an updated file. $read is indeed faster with that one!

-a doesn't do anything (or it does the same as /linesep without switches), the reason I use it is for consistency with other commands; /echo -a echoes to the active window, /linesep -a adds a line separator to the active window.
edit nvm, I was wrong
If you want to handle each match from the file in the specified text:
Code:
/findit this line of text would get searched
$findit(this line of text would get searched)

alias findit {
  if (!%findit:lookup) {
    set %findit:lookup $1-
    
    ;this assumes file.txt is in your mIRC dir
    filter -fk $qt($mircdirfile.txt) findit *
    
    var %c = %findit:count
    unset %findit:*

    ;This is after searching is done
    ; %c is the total number of matches found
    $iif($isid,return,echo -a Total Matches Found:) %c
  }
  elseif (!$2 && $isid && $gettok($1,1,59) isin %FindIt:lookup) { 
    inc %findit:count 

    ;this is where you would handle the matches
    ;  %FindIt:Count is the match number
    ;  %FindIt:Lookup is the text that is being searched
    ;  $1- is the match from the file

    echo 03 :: $1-
  }
}


I tested it using the contents of the file
Quote:
csi.miami;scripted;us
prison.break;scripted;us
the.mentalist;scripted;us
UEFA.CHAMPIONS.LEAGUE;SPORTS;SOCCER
...(repeated 10 times)


Calling:
Code:
/findit I am looking for csi.miami.2.522.02 and the.mentalist.457 in my file!



Ran it 25x, found 20 matches in each search(echo'd out), then total number of matches found echo'd out

Each search with echoing taking ~.25s(ticks being inaccurate and all)
Originally Posted By: FroggieDaFrog
If you want to handle each match from the file in the specified text:
Code:
/findit this line of text would get searched
$findit(this line of text would get searched)

alias findit {
  if (!%findit:lookup) {
    set %findit:lookup $1-
    
    ;this assumes file.txt is in your mIRC dir
    filter -fk $qt($mircdirfile.txt) findit *
    
    var %c = %findit:count
    unset %findit:*

    ;This is after searching is done
    ; %c is the total number of matches found
    $iif($isid,return,echo -a Total Matches Found:) %c
  }
  elseif (!$2 && $isid && $gettok($1,1,59) isin %FindIt:lookup) { 
    inc %findit:count 

    ;this is where you would handle the matches
    ;  %FindIt:Count is the match number
    ;  %FindIt:Lookup is the text that is being searched
    ;  $1- is the match from the file

    echo 03 :: $1-
  }
}


worked perfect as i described... thanks alot.
© mIRC Discussion Forums