mIRC Home    About    Download    Register    News    Help

Print Thread
#221758 29/05/10 12:45 AM
Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
Code:
on 1:Text:!calc *:*: {
  if ($isOnExceptionList($chan)) { halt }
  if ($flood) { halt }
  if ($evilreply) { halt }
  msg # Calc: $2- = $calc($2-)
}


I suspect regex is the best way to help with this, but I don't know how to use regex for this. Reading through information regarding regex I still haven't found what I'm after. I'm looking for a way to take the $2-, and have it find every mathematical operator, change it to the appropriate identifier (deleting all instances of the $ character before doing creating the identifiers), then evaluate the string with $eval prior to using $calc on it. It needs to only match identifiers used for math, or those that I specify if I make custom ones, so as to prevent a type of exploit that would allow a person to run commands I don't want just anyone running (no tricks with $quit or the like). Anyone know how to set this up?

By the way, you can ignore the first 3 lines in the On Text trigger. The first one prevents the script from running in channels where people don't want scripts running, the second one just makes sure I don't get flooded with requests, and the third one is a joke thing I can enable for laughs. The order is intentional, so I don't plan on putting them in the same line.

Edit: I created something with some help in a chat, but it doesn't seem to work.

Code:
alias -l makeIdentifiers {
  var %arg $remove($1-,$chr(36))
  var %regexIdentifierMatch \b[A-Za-z]+\(
  var %matches $regex(Identifiers,%arg,%regexIdentifierMatch)
  echo -s Matches: $+ %matches
  var %a 1
  while (%a <= %matches) {
    var %match $regml(Identifiers,%a)
    echo -s Match: $+ %match
    if ($istok($identifierList,%match,44)) {
      var %arg $replace(%arg,%match,$chr(32) $+ $chr(36) $+ %match)
    }
    inc %a
  }
  return %arg
}

The first echo says one value was matched, but the second echo is blank, it shows Match:, but not the matched value. The string passed through it was ceil(2.5). It seems $regml is returning $null.

Last edited by KageNoOni; 29/05/10 01:39 AM.
Joined: Jul 2007
Posts: 1,129
T
Hoopy frood
Offline
Hoopy frood
T
Joined: Jul 2007
Posts: 1,129
Quote:
By the way, you can ignore the first 3 lines in the On Text trigger.
Well, you could have done it as:
Code:
on 1:Text:!calc *:*: {
if ((!$isOnExceptionList($chan)) && (!$flood) && (!$evilreply)) {
  msg # Calc: $2- = $calc($2-)
}
Quote:
I'm looking for a way to take the $2-, and have it find every mathematical operator, change it to the appropriate identifier (deleting all instances of the $ character before doing creating the identifiers)
Sounds like you should be able to use $regsubex and $replace for this operation.

Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
I need it to stop checking further if any of them evaluate to true. The second one manipulates variables, and the third one actually sends a message to a chat (if the third one evaluates to true), this is why I keep them seperate.

The reason I don't use $regsubex is the risk of evaluating identifiers I don't want evaluated. This is why I was using $regml, but it is returning $null instead of the matches found by $regex.

Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
Looks like I just needed an extra set of parenthesis in the $regex, it works now.

Edit: It seems to only be finding the first match, but nothing after that. Any idea why it can't seem to find more than one match when I run this?

Code:
alias -l makeIdentifiers {
  var %arg $remove($1-,$chr(36),$chr(37))
  var %regexIdentifierMatch ([A-Za-z]+\()
  var %matches $regex(Identifiers,%arg,%regexIdentifierMatch)
  echo -s Matches: $+ %matches
  var %a 1
  while (%a <= %matches) {
    var %match $regml(Identifiers,%a)
    echo -s Match: $+ %match
    if ($istok($identifierList,%match,44)) {
      var %arg $replace(%arg,%match,$chr(32) $+ $chr(36) $+ %match)
    }
    inc %a
  }
  return %arg
}

Originally Posted By: Status Window
Matches:1
Match:int(
Calculating $int(2.5) + abs(-3).
Matches:1
Match:abs(
Calculating $abs(-3) + int(2.5)

Last edited by KageNoOni; 29/05/10 09:02 AM.
Joined: Aug 2004
Posts: 7,252
R
Hoopy frood
Offline
Hoopy frood
R
Joined: Aug 2004
Posts: 7,252
You need the /g switch in your regex for it to recognize more than just the first match. My knowledge of regex is minimal, but that is the switch you are missing.

Joined: Jul 2007
Posts: 1,129
T
Hoopy frood
Offline
Hoopy frood
T
Joined: Jul 2007
Posts: 1,129
RusselB is right. You need the /g modifier to make regex greedy in searching for the match globally.
Quote:
/([A-Za-z]+\(\))/g

Joined: Aug 2006
Posts: 183
T
Vogon poet
Offline
Vogon poet
T
Joined: Aug 2006
Posts: 183
Originally Posted By: Tomao
RusselB is right. You need the /g modifier to make regex greedy in searching for the match globally.
Quote:
/([A-Za-z]+\(\))/g


/g is actually for "global". Greedy is for repetition in regex.
http://www.regular-expressions.info/repeat.html

Edit: Never mind. Reading comprehension failure.

Last edited by Thrull; 30/05/10 01:43 AM.

Yar
Joined: Jul 2007
Posts: 1,129
T
Hoopy frood
Offline
Hoopy frood
T
Joined: Jul 2007
Posts: 1,129
Right. I was meaning to say it as global...hence I noted "globally." at the end of my sentence.

The /g modifier can sometimes be mistaken for greedy mode in regex...because of the "g"

Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
Odd, all the info I could find on regex never mentioned anything about this /g switch.

/([A-Za-z]+\(\))/g

To enhance my understanding of Regex, what are the parts I put in red for? Why did you add a / to the front? I have no idea what this would do. Escaping the ) in the original regex I put up doesn't really help me, as I don't want to search for a literal end parenthesis, so why is it escaped here? My goal was to find a string of letters, followed by (, and that's all the match I was after. Also, why the second parenthesis at the end? My guess regarding the last 2 is to have it search for the ), which I don't want matched, and if that's the case, I can probably remove them, but it still doesn't explain the / at the beginning of this one.

Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
Ok, I took out the second 2 red characters, and put that in my regex match, and it works beautifully so far. Thanks for the help, but I would like to learn more about regex, as I can really see the power behind the tool. So if I could get the questions above answered it would be very helpful.

Joined: Nov 2006
Posts: 1,559
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Nov 2006
Posts: 1,559
/([A-Za-z]+\(\))/g
They are delimiters - to delimit your string from the modifiers/switches like "g" for global, "S" for strip, or "i" for case-insensitive.

You need to know that if an expression starts with the "m" char, the next char will be used as the delimiter. The "/" char is the "default" delimiter, and does not require the leading "m". Any char can be used as a delimiter: "m/test/g" is the same as "/test/g" or "m@test@g". And if you want to match the delimiter literally, you have to escape it of course.

Delimiters aren't required all the time, but it's a good habit to always put them:
While $regex(go test me,test) will do the same as $regex(go test me,/test/), $regex(surround,mono) will find a match - to some people's surprise - as it uses the "o"'s of "mono" as delimiter, thus matches like $regex(surround,m/n/) - which is the same as $regex(surround,n).

Here is more info about it. smile




Joined: Mar 2009
Posts: 74
K
Babel fish
OP Offline
Babel fish
K
Joined: Mar 2009
Posts: 74
Thanks for the link, it's a great help.

Joined: Jul 2007
Posts: 1,129
T
Hoopy frood
Offline
Hoopy frood
T
Joined: Jul 2007
Posts: 1,129
The /S (capital letter s) modifier, I believe, is solely for mIRC to strip control codes.


Link Copied to Clipboard