Forum Discussion

David_Noonan_67's avatar
David_Noonan_67
Icon for Nimbostratus rankNimbostratus
Oct 08, 2007

Syntax for "matches" and "matches_regex"

We've got an iRule that contains the following code. It works fine but I find the repetition offensive.

 

 


  elseif {[HTTP::uri] contains "fx1"} {
   use pool Xyzzy
  }
  elseif {[HTTP::uri] contains "fx2"} {
   use pool Xyzzy
  }
  elseif {[HTTP::uri] contains "fx3"} {
   use pool Xyzzy
  }
  elseif {[HTTP::uri] contains "fx4"} {
   use pool Xyzzy
  }

 

 

I thought this could be replaced with something like this

 

  elseif {[HTTP::uri] matches "fx[1234]"} {
   use pool Xyzzy
  }

 

but it complains about"extra tokens at end of expression". So I tried this

 

  elseif {[HTTP::uri] matches_regex "fx[1234]"} {
   use pool Xyzzy
  }

 

But that complains about an undefined procedure.

 

 

Can someone point me at a working example of the matches and/or matches_regex using a character range? The examples shown on the wiki are overly simple and therefore not very useful.

 

 

Thanks

6 Replies

  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Use {} to delimit the match expression instead of "" and you should be good to go:

      elseif {[HTTP::uri] matches_regex {fx[1234]}} {
       use pool Xyzzy
      }
    (wiki example updated)

    /deb
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    boy, some funky substitution is taking place there....

     

     

    that should read:

     

    open brace, fx, open square, 1234, close square, close brace

     

     

    with no commas or whitespace.

     

     

    /deb
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Just realized you'd have to also include some wildcards if you want to simulate the "contains" command:
      elseif {[HTTP::uri] matches_regex {.*fx[1234].*}} {
       use pool Xyzzy
      }

    which should read:

    open brace, period, asterisk, fx, open square, 1234, close square, period, asterisk, close brace

    /deb
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Braces may be used to prevent interpretation of strings surrounded by [] as commands, as you experienced ("undefined procedure").

     

     

    As long as there isn't a variable inside the braces that requires expansion, you can use them in most cases instead of "", and they can actually be more efficient, if harder to type & read.

     

     

    Colin wrote an excellent tech tip recently about using {} with numbers to prevent the tcl interpreter from having to figure out if they are strings or not before performing the operation: http://devcentral.f5.com/Default.aspx?tabid=63&articleType=ArticleView&articleId=110 (Click here)

     

     

    (Someday I'm going to have to go re-work all of my codeshare examples to take advantage of that optimization...)

     

     

    HTH

     

    /deb
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Deb, thanks for the link to Colin's tips on avoiding conversions...

    noonand, you could also use string wildcards to do this and avoid the more expensive regex evaluation. Here's an example using string match:

    
    elseif {[string match {*fx[1-4]*} [HTTP::uri]]} {
       pool Xyzzy
    }

    If you're doing multiple URI tests, it would probably be faster to use a switch statement:

    
    when HTTP_REQUEST {
       switch -glob [HTTP::uri] {
          {*fx[1-4]*} { pool test_http_200_pool}
       }
    }

    As Deb said, the string should read:

    open brace, asterisk, "fx", open square, 1-4, close square, asterisk, close brace

    Aaron
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Looks like Joe fixed the character display substitution issue - thanks Joe!

    Great points, hoolio. Definitely more optimal approach. I didn't realize you could use charsets with either string match or switch.

    I just came back to point out that for the regex with braces, you can instead escape the [] with a backslash to prevent the interpreter from trying to execute as a command:
    if {"testfx4xxx" matches_regex ".*\[1234\].*"} {

    /deb