Monday, March 28, 2011

PHP Regex Problem - /i caseless not working and weird empty array elements.

Source texts (7):

  1. give 4 cars
  2. ga 5 cars
  3. GA 5 Cars @mustang six exhausts are necessary
  4. Give -1 Cars @mustang
  5. Give Cars @mustang
  6. Give 3 Cars @ford
  7. Give 5 Cars @cobra_gt

The ones which should be successful ate 1,2,3,6,7

preg_match('/Give (\d+) Cars @(\w+)|GA (\d+) Cars @(\w+)/i', $a->text, $output);

print_r($output); produces:

Array
(
)
Array
(
)
Array
(
    [0] => GA 5 Cars @mustang
    [1] => 
    [2] => 
    [3] => 5
    [4] => mustang
)
Array
(
)
Array
(
)
Array
(
    [0] => Give 3 Cars @ford
    [1] => 3
    [2] => ford
)
Array
(
    [0] => Give 5 Cars @cobra_gt
    [1] => 5
    [2] => cobra_gt
)

As you can see it is not working with the lowercase ones, and for number #3 it doesn't produce the right array, it produces empty elements. Any idea where I am going wrong here?

Thank you very much,

Ice

From stackoverflow
  • 1 and 2 are missing @ 4 has -1 (this doesn't match \d) 5 is missing the number

    you could change " @" to "( @)?" to make the @ optional.

    Or:

    preg_match('/(Give|GA) (-?\d+) Cars( @(\w+))?/i', $a->text, $output);
    

    About the empty array elements, you have 4 submatches, even though they are seperated by an or (|), they all count, and only the ones used in your match will be populated.

  • Given the input:

    1. give 4 cars
    2. ga 5 cars
    3. GA 5 Cars @mustang six exhausts are necessary
    4. Give -1 Cars @mustang
    5. Give Cars @mustang
    6. Give 3 Cars @ford
    7. Give 5 Cars @cobra_gt

    And the expression:

    /Give (\d+) Cars @(\w+)|GA (\d+) Cars @(\w+)/i
    
    1. Does not match because you are only matching against something that has "@something" in it.
    2. Same as #1
    3. This matches as expected
    4. The - in front of 1 causes the match to fail
    5. There is no number between Give and Cars
    6. This matches as expected
    7. This matches as expected

    As to why it doesn't produce the "right" array, it actually is. In your expression you have 4 capture groups. Just because your input matches the second of the OR'd expressions (the 'GA' one) doesn't mean the group numbers start at 1, the groups will always have the same number, no matter how you match, so...

    /Give (\d+) Cars @(\w+)|GA (\d+) Cars @(\w+)/i
          ^ 1         ^ 2      ^3          ^4
    

    So if you match the 'Give' case, you are going to have groups 1 and 2, and if you match the 'GA' case, groups 3 and 4 will be filled.

    (Also, the 'i' modifier is working fine, you just aren't properly accounting for your inputs)

    Ice : Thank you very much - I noticed my mistakes - thank you!

0 comments:

Post a Comment