Excluding groups in regexp...

Posted by NeoFryBoy on Sun 11 Jun 2006 10:53 AM — 8 posts, 31,078 views.

USA #0
I made a trigger that matches on...
^([ ]{5}|\(( \d|\d+)\) )(\([B-M]\))+ (.*?) (|\[\d+\/\d+\] )(?:\[\d+\])

Which means that if my inventory looks something like this:

     a dragon axe [83] 
     (G) a small blue key [0] 
( 2) (K)(M)(G)(H) a Bag of Aardwolf [91]


it will grab only the item name and number of items in the inventory, ignoring the level and enchantment flags.

My problem is that with the addition of (\([B-M]\))+ it will only match on items that have these flags in them (so in this case it won't match on the dragon axe), so is there a way that I can set it to grab lines that don't have these flags as well as lines that do?

I tried (|\([B-M]\) )+, to signify a flag OR null but it doesn't work.

I can just remove it and pull out the flags in the scripting if I have to...

Edited by Nick to add [code] tags.
Amended on Mon 12 Jun 2006 12:32 AM by Nick Gammon
Australia #1
I am not familiar with this MUD, but each flag in your output is not followed by a space, only one at the end.

Try replacing with (|(\([B-M]\))+). This will match on none, or at least one flag with possibly more.

Alternatively use (\([B-M]\))* to match zero or more.
Amended on Sun 11 Jun 2006 01:53 PM by Cino
USA #2
Firefox web browser has a regular expressions tester extension that you can use to test out regular expressions. It'd be cool if mushclient's Test trigger worked as easily as this little extension does. https://addons.mozilla.org/firefox/2077/
Australia Forum Administrator #3
You can write a small script (which could go into a plugin) to make a regexp-tester. The Lua rex library provides an interface to the same regexp matcher used in triggers and aliases. For example:


re = "(?P<who>.+) goes (?P<where>.+)"
targetstring = "Nick goes East"

s, e, t = rex.new (re):match (targetstring)

if s then
  print ("Matched! Start = ", s, ", end = ", e)
  tprint (t)
else
  print ("No match.")
end -- if

Output

Matched! Start =  1 , end =  14
1="Nick"
2="East"
"where"="East"
"who"="Nick"


This assumes the use of "tprint" from the shipped exampscript.lua file. You can get a very similar result by changing the line:


  tprint (t)


to:


 table.foreach (t, print)



I tried out your regexp with a slight variation and it seemed to work. The only problem with using this technique is you have to double the backslashes because they have meaning inside strings:


re = "^([ ]{5}|\\(( \\d|\\d{2})\\) )(\\([B-M]\\))+ (.*?) (|\\[\\d+\\/\\d+\\] )(?:\\[\\d+\\])"

targetstring = "( 2) (K)(M)(G)(H) a Bag of Aardwolf [91]"

Output

Matched! Start =  1 , end =  40
1 ( 2) 
2  2
3 (H)
4 a Bag of Aardwolf
5 

Australia Forum Administrator #4
To save mucking around doubling backslashes you could use this variant, which uses input boxes to ask for the regular expression, and the test string:


newre = utils.editbox ("Enter the regular expression", 
                      "Regexp test", 
                      re, "Courier New")

if not newre then
  return
end -- if

re = newre

newtargetstring = utils.editbox ("Enter the string to match against",
                                 "Regexp test", 
                                 targetstring, "Courier New")

if not newtargetstring then
  return
end -- if

targetstring = newtargetstring 

s, e, t = rex.new (re):match (targetstring)

if s then
  print ("Matched! Start = ", s, ", end = ", e)
  table.foreach (t, print)
else
  print ("No match.")
end -- if



This version defaults to the previous entry in the input box, so you can just press <enter> to re-use it (eg. re-use the target string) or make minor changes to it.

Now I can just enter the regexp:

Regexp: ^([ ]{5}|\(( \d|\d{2})\) )(\([B-M]\))+ (.*?) (|\[\d+\/\d+\] )(?:\[\d+\])

And the target string:

Target string: ( 2) (K)(M)(G)(H) a Bag of Aardwolf [91]

I did this in the "Immediate" dialog but you could turn it into an alias.

Amended on Mon 12 Jun 2006 01:13 AM by Nick Gammon
USA #5
THat's pretty cool, Nick.

Turns out
(?:\([BKIGHM]\)){0,} and (?:\([BKIGHM]\))* work to match Zero or more. Thanks Cino.

There's also various tester sites available online. This was the best I found http://www.roblocher.com/technotes/regexp.aspx
Australia Forum Administrator #6
Sure, but that one uses the Javascript regexp parser, not the one in MUSHclient (which is the PCRE one).

For one thing, it didn't recognise the (?P<name> blah ) syntax that the PCRE one supports.

However with simpler regular expressions that would probably be fine.
USA #7
Yo NeoFryBoy I see the a bag of Aardwolf, my username is Venificius on that mud, what is your?

If you are not comfortable posting it for ALL to see you can e-mail me it, or even post me a note in-game

I have made several plugins for the MUD and would love to share them with a fellow Aardwolf'er

Laterzzz,
Onoitsu2
(Venificius on Aardmud.org)