Regexp trouble

Posted by Funkenstein on Thu 01 Apr 2010 11:58 AM — 11 posts, 45,155 views.

#0
I am trying to adapt the inventory miniwindow to show my current affections. However, all attempts at trying capture what I need/want has failed and I am a little stumped.

The output shows as follows:

>You are affected by:
detect magic                (long)
detect hidden               (long)
slow digestion              (long)
evasion                     (short)
regeneration                (fast-acting)


I want to be able to capture just the name of the affection and store that in a table but cant seem separate it from the whole line.

Any help is appreciated

Thanks in advance
Amended on Thu 01 Apr 2010 12:06 PM by Funkenstein
Netherlands #1
I don't have the source of said plugin handy, but I can give you the regular expression needed.

^(.+)\s+\([^]]+\)


You may want to add another $ at the end in case it ends up matching too much. To get to the value from within a Send-to-script trigger, use %1. From a pure script, use wildcs[1] or whatever the precise variable is named that is used for that specific purpose in the script.
#2
Thanks worstje, although I am still having trouble with the regexp. I'm posting the code from the alias so hopefully that will give people more of an idea. The window works if I use the capture (.*?), but as soon as I start trying to be more specific than that, it doesn't seem to work.


  require "wait"

  wait.make (function ()  -- coroutine starts here


  local win = GetPluginID () .. ":affection"  -- get a unique name
  local font = "f"

  -- request inventory

  Send "aff"

  local x = wait.regexp ("^(?:.*>)?(?J)You are affected by\:$", 10)

  if not x then
    ColourNote ("white", "blue", "No affection received within 10 seconds")
    return
  end -- if

  aff = {}

  -- loop until end of inventory

  while true do
    local line, wildcards = wait.regexp("^(.+)\s+\([^]]+\)")
    affection = wildcards[1]
    -- see if end of inventory

    if string.match (line, "^$") then
      break
    end -- if
    -- save inventory line
    aff [affection] = 0

  end -- while loop
  
  require "tprint"
  tprint (aff)
  WindowFont (win, font, "Lucida Console", 10)
  WindowCreate (win, 0 , 0, 150, GetInfo (212) * 20, 10, 0, ColourNameToRGB ("#003200"))  -- create window
  WindowRectOp (win, 5, 0, 0, 0, 0, 5, 15)
  WindowText (win, font, "Affections", 5, 5, 0, 0, ColourNameToRGB  "yellow")

  -- draw each affection line

  local font_height = WindowFontInfo (win, font, 1)
  local y = font_height * 2 + 5

  for k, v in pairs (aff) do

    local x = 5
  
    x = x + WindowText (win, font, k, x, y, 0, 0, ColourNameToRGB ("white"))

    y = y + font_height

  end -- for each affection

  WindowShow (win, true) 

end)   -- end of coroutine
Australia Forum Administrator #3
I tested that regexp in this trigger and it seemed to match:


<triggers>
  <trigger
   enabled="y"
   match="^(.+)\s+\([^]]+\)"
   regexp="y"
   send_to="2"
   sequence="100"
  >
  <send>
%%1 = '%1'
</send>
  </trigger>
</triggers>


There were some trailing spaces in wildcard 1 but you can use Trim to get rid of those.
Netherlands #4
Ah, that explains a lot, Funkenstein. You are using the regexp in Lua code, and of course the backslashes will need escaping (\ becomes \\):

Try this:

local line, wildcards = wait.regexp("^(.+)\\s+\\([^]]+\\)")


Oi. Forum is eating my backslashes. Fixed on the third edit. Woo.
Amended on Fri 02 Apr 2010 03:34 PM by Worstje
Germany #5
I think this[1] is worth to read (for people using Lua)

[1] http://www.lua.org/manual/5.1/manual.html#5.4.1
#6
I modified the capture to not need Trim.
It works in a normal trigger, "^\w+(|\s\w+)\s+([^]]+\)" however when I add the extra backslashes, it doesn't seem to capture anything.
Also, if the list of affections is always followed by a blank line, is the check to see if it is the end correct?

  while true do
    local line, wildcards = wait.regexp("^(\\w+(|\\s\\w+))\\s+\\([^]]+\\)")
    Note (wildcards[1])
    affection = wildcards[1]
    -- see if end of affections

    if string.match (line, "^$") then
      break
    end -- if

    -- save affection
    aff [affection] = 0
  end -- while loop


Thanks
Amended on Fri 02 Apr 2010 10:43 PM by Funkenstein
Australia Forum Administrator #7
Funkenstein said:

if string.match (line, "^$") then


It would be simpler to say:


if line == "" then

#8
Not sure if this is meant to happen, but I've been trying to figure out why it doesn't capture in the script, but does in normal trigger. I changed the alias to a trigger so it would create the wait.regexp trigger to match:

"^\\w+(|\\s\\w+)\s+([^]]+\\)"

I used the double blackslashes within the script, but when I checked the trigger, it was made to capture

^(w+(|sw+))s+([^]]+)

Any suggestions on why its getting rid of my backslashes?


<triggers>
  <trigger
   enabled="y"
   match="^(?:.*&gt;)?(?J)You are affected by\\:$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>  require "wait"

  wait.make (function ()  -- coroutine starts here

  local win = GetPluginID () .. ":affector"  -- get a unique name
  local font = "f"

  aff = {}

  -- loop until end of affections

  while true do
    local line, wildcards = wait.regexp("^(\\\w+(|\\\s\\\w+))\\\s+\\\([^]]+\\\)")
    Note (wildcards.affection)
    affection = wildcards[1]

    if line == "" then
      break
    end -- if

    -- save affection line
    aff [affection] = 0
 

  end -- while loop

  
  WindowCreate (win, 0 , 0, 150, GetInfo (212) * 20, 10, 0, ColourNameToRGB ("#003200"))  -- create window
  WindowFont (win, font, "Lucida Console", 10)
  WindowRectOp (win, 5, 0, 0, 0, 0, 5, 15)
  WindowText (win, font, "Affections", 5, 5, 0, 0, ColourNameToRGB  "yellow")

  -- draw each affection line

  local font_height = WindowFontInfo (win, font, 1)
  local y = font_height * 2 + 5

  for k, v in pairs (aff) do

    local x = 5
  
    x = x + WindowText (win, font, k, x, y, 0, 0, ColourNameToRGB ("white"))

    y = y + font_height

  end -- for each affection

  WindowShow (win, true) 

end)   -- end of coroutine
</send>
  </trigger>
</triggers>



Thanks in advance

Amended on Sun 04 Apr 2010 05:43 AM by Nick Gammon
Australia Forum Administrator #9
Thinks get a bit confusing here because I don't think you escaped the backslashes for the forum, which also reduces two backslashes to one. I edited your post to do that, so we are looking at the right thing.

See this post for a bit more detail:

Template:post=9691
Please see the forum thread: http://gammon.com.au/forum/?id=9691.


Now it seems to me (if I got your post fixed up correctly), that you are still a backslash short:


\\\w+


That is only 3 when I expect to see 4 (or is it 2?) Anyway, that doesn't look right.
Netherlands #10
Aye, 3 levels of escaping is impossible when you are dealing with backslash escaping only. They double with each layer of escaping. From one backslash to two backslashes to four backslashes to eight backslashes to 16 backslashes to... let's hope you won't make it this far. :)