Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ General ➜ Regex, default capture group value?

Regex, default capture group value?

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by j0nas   (56 posts)  Bio
Date Wed 05 Jan 2011 04:40 PM (UTC)
Message
This is a little bit hard to explain, so I'll skip the circumstances that led me to needing this particular solution and just skip straight ahead to my problem.

I'm using regex triggers with named groups, and there are some special cases in which it would be very convenient if I could give one or several of the named groups in the regex default values, even if they are never present in the pattern as actual catching groups. Is this possible?

For example, input normally looks like this:
You crave bread!
You crave wine!
..so I use a pattern like '^You crave (?<craving>.*?)!$' and things work just fine.

But in some special cases, it looks like this:
You crave OMNOMNOM crumbly goodness!
..in which case I would like to be able to use a trigger like '^You crave OMNOMNOM crumbly goodness!$' BUT have the rest of the trigger evaluate as if the capture-group 'craving' had matched 'cookie'. This seems like something an advanced feature of regex might be able to pull off, but how? Am I the only one to ever have had this need?
To further clarify, I imagine such a pattern might look something like '(?assign:<craving>=cookie)^You crave OMNOMNOM crumbly goodness!$', giving the capture group a initial value to be used in case there are no other matches, or something like that.


( Of course I'm aware that there are many other possible workarounds I could use, but this is just a simplified example. In my real scenario it would simply be a lot more convenient if it were possible to do things as described above, but is that even possible? )
Top

Posted by Bast   (78 posts)  Bio
Date Reply #1 on Wed 05 Jan 2011 07:18 PM (UTC)
Message
Keep the same regex, but have a table that you can substitute with if need be.


replacestuff = {
 "OMNOMNOM crumbly goodness" = "cookie",
 "Something else here" = "bread",
}


Then at the top of your function for the trigger do something like this:

if replacestuff[wildcards.craving] then
  wildcards.craving = replacestuff[wildcards.craving]
end


and then go about doing whatever is you wanted to do.

When you figure out something else you need to replace, just add it to the table. No new triggers.

Bast

Bast

Scripts: http://github.com/endavis
Top

Posted by j0nas   (56 posts)  Bio
Date Reply #2 on Wed 05 Jan 2011 07:29 PM (UTC)
Message
Bast said:

Keep the same regex, but have a table that you can substitute with if need be.


replacestuff = {
 "OMNOMNOM crumbly goodness" = "cookie",
 "Something else here" = "bread",
}


Then at the top of your function for the trigger do something like this:

if replacestuff[wildcards.craving] then
  wildcards.craving = replacestuff[wildcards.craving]
end


and then go about doing whatever is you wanted to do.

When you figure out something else you need to replace, just add it to the table. No new triggers.

Bast
Yes, you're right, that would work just fine for the example, but like I said the actual case I have is a lot more complicated than just the example and so that approach would not be nearly as neat. I guess my example was poorly thought out, but I didn't want to over-complicate things.

So I'm still looking for a solution that would 'keep it all in the regex', as it were.
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #3 on Wed 05 Jan 2011 08:47 PM (UTC)
Message
j0nas said:

I'm using regex triggers with named groups, and there are some special cases in which it would be very convenient if I could give one or several of the named groups in the regex default values, even if they are never present in the pattern as actual catching groups. Is this possible?


No, I don't think so. I didn't write the regexp stuff, and I don't believe that feature is in the library.

Basically you are wanting it to return a capture which doesn't even exist in the source text. I doubt it will ever do that. In your example you want it to "capture" the word "cookie" which isn't present in the text.

All I can really do is agree with Bast, and recommend some sort of post-processing. Indeed when regexps start getting really complicated it can be time to simply capture a simple wildcard, and then drop into scripting to make those sort of decisions.

Here's one suggestion ... assuming you have some sort of way of identifying the problem triggers (eg. a trigger group) you could simply say something like this:


if wildcards.craving == "" then
  wildcards.craving = "cookie"
end -- if


Since the ordinary case will have the craving type supplied, it will be untouched, but the nomnomnom case will have no craving, and you put the "default" in after the event.

Here's an example. Two triggers:


<triggers>
  <trigger
   custom_colour="2"
   enabled="y"
   match="^You crave OMNOMNOM crumbly goodness!(?&lt;craving&gt;)$"
   regexp="y"
   script="mytrigger"
   sequence="90"
  >
  </trigger>

  <trigger
   custom_colour="2"
   enabled="y"
   match="^You crave (?&lt;craving&gt;.*?)!$"
   regexp="y"
   script="mytrigger"
   sequence="100"
  >
  </trigger>
</triggers>


Both have the "craving" group, but in the case of OMNOMNOM crumbly goodness it just matches an empty string. However this means the group "craving" will exist in both cases.

Now your script looks like this:


function mytrigger (name, line, wildcards, styles)

  if wildcards.craving then  -- group exists?
    if wildcards.craving == "" then 
      wildcards.craving = "cookie"  -- take default
    end -- if
  end -- if
  
  print ("craving=", wildcards.craving)
end -- mytrigger



The first test is whether or not the craving group exists (it does in both cases). The second test says that if the group exists, but is empty, we assume cookie. That would seem to address your issue.

Example output:


You crave OMNOMNOM crumbly goodness!
craving= cookie
You crave fish!
craving= fish


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by j0nas   (56 posts)  Bio
Date Reply #4 on Thu 06 Jan 2011 03:14 AM (UTC)
Message
Again that solution works well for the given example, but for my actual usage that doesn't work out very well at all. At least I can be sure that there's no near-magical regex trick I can use to pull a rabbit out of my hat, thanks Nick, Bast!

If I manage to find some solution that ends up working out neater than the ways already suggested, I'll come back and write it up, but I doubt I can find one.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


18,848 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.