pcre returning shortest match

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • redbeardmcg
    New Member
    • May 2009
    • 3

    pcre returning shortest match

    Hi everyone,

    I'm having an issue splitting a string with preg_split.... Here is a sample string:

    Code:
    congestion >= 80
    Where >= could also be <=, ==, !=, < or >

    What I need to accomplish is splitting this, and put each of the three parts (item, operator, value) into an array.... Here is how I'm doing this:

    Code:
    $this_expr = preg_split('/(==|>=|<=|<|>|\!=)/U', $rule, -1, PREG_SPLIT_DELIM_CAPTURE);
    This works great so long as the operator is one of ==, !=, <, or >.... but where the operator is >= or <= (as in this case) pcre matches ONLY the > or < so that the resultant array looks like this:

    Code:
    $this_expr[0] = congestion;
    $this_expr[1] = >;
    $this_expr[2] = =80;
    Clearly the operator should be >= and the value should be only 80.... Any ideas of how I could get around this? I did try changing the order (put >= | <= after the < | > in the sub-patter) to no avail... It seems to return only the shortest match.

    I could of course write a HACK (if the value starts with = append it to the operator and strip it from the value) but I am so dead set against hacking things together that it hurts me to even consider that as an option.

    Thanks!

    -Ryan
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    what about a character class?
    Code:
    [<>=!]{1,3}

    Comment

    • Atli
      Recognized Expert Expert
      • Nov 2006
      • 5062

      #3
      Hi.

      This doesn't seem to happen on my side.
      I tried this code:
      [code=php]<?php
      header("content-type: text/plain");

      $str = "congestion >= 80";
      $reg = '/(==|>=|<=|<|>|\ !=)/U';

      $out = preg_split($reg , $str, -1, PREG_SPLIT_DELI M_CAPTURE);

      print_r($out);
      ?>[/code]
      And I got these results:
      Code:
      Array
      (
          [0] => congestion 
          [1] => >=
          [2] =>  80
      )
      Isn't that what you would expect?

      P.S.
      Using PHP 5.2 over here.

      Comment

      • redbeardmcg
        New Member
        • May 2009
        • 3

        #4
        Thank you both for the responses... Dormilich, your example should work however I think you need to change [<>=!]{1,3} to [<>=!]+ to make it more greedy.

        Atli, I'm running php 5.1.6 :-/

        I did however realize that I am totally over-engineering this.... They are always separated by a space... Using explode(' ', $string) works more than fine!

        Sometimes simple is better.

        Thanks again!

        -Ryan

        Comment

        • Dormilich
          Recognized Expert Expert
          • Aug 2008
          • 8694

          #5
          Originally posted by redbeardmcg
          however I think you need to change [<>=!]{1,3} to [<>=!]+ to make it more greedy.
          ... if you use operators longer than 4 characters... anyway REs are in greedy mode by default.

          Comment

          • Atli
            Recognized Expert Expert
            • Nov 2006
            • 5062

            #6
            Originally posted by redbeardmcg
            Dormilich, your example should work however I think you need to change [<>=!]{1,3} to [<>=!]+ to make it more greedy.
            How about: '/\s*?([<>=!]{1,3}?)\s*?/U'.
            Even strips away the spaces.

            Anyways, glad you found a solution :)

            Comment

            • redbeardmcg
              New Member
              • May 2009
              • 3

              #7
              You're absolutely right, I spoke too soon. Thanks again guys!

              -Ryan

              Comment

              • Markus
                Recognized Expert Expert
                • Jun 2007
                • 6092

                #8
                Originally posted by Atli
                How about: '/\s*?([<>=!]{1,3}?)\s*?/U'.
                Even strips away the spaces.

                Anyways, glad you found a solution :)
                Being slightly picky here, I apologise.

                Wouldn't that allow for ==>, ==<, etc? Not sure if you are bothered about it, but if you are, you could improve it a little.

                Maybe: '/\s*?([<>!]{1}[=]{1,2}?)\s*?/U'

                Would the square brackets be needed around the '='? Also, would the above work? I haven't tested it.

                Mark (off to read Lemony Snicket's: A Series of Unfortunate Events :)

                Comment

                • Atli
                  Recognized Expert Expert
                  • Nov 2006
                  • 5062

                  #9
                  Yea, that's even better. Makes sure you don't get matches on operators like <<< or >>=.

                  Originally posted by Markus
                  Would the square brackets be needed around the '='? Also, would the above work? I haven't tested it.
                  No, you don't need to create a character class for a single char.
                  You can just do: '={1,2}'

                  Originally posted by Markus
                  Mark (off to read Lemony Snicket's: A Series of Unfortunate Events :)
                  A very good story. One of my favorites :)
                  (The movie was good to... Well, how could it not; starring Jim Carrey :P)

                  Comment

                  Working...