There's this simple regular expression that has got me stumped. I was hoping someone could shed some light on this.

Here's my expression.

preg_match('/(.*)(i)?/','quit',$args);

print_r($args);
/*
Example 1.
Array
(
    [0] => quit
    [1] => quit
)
*/


preg_match('/(.*)(i)/','quit',$args);
/*
Example 2.
Array
(
    [0] => qui
    [1] => qu
    [2] => i
)
*/

If someone could explain why both these expression don't produce the same results. Aside from the first having '?'.

Essential what I want is the result displayed in 'Example 2', with the '(i)' being optional.

    The way I see it, in the first one, if i is optional, (.) behaves greedy and "eats" the whole word. I tried /(.?)(i)?/ to make it ungreedy, but it doesn't work. Some regex expert is needed.

      The only way I can see to get what I think you are after is:

      preg_match('/([^i]*)(i)?/','quit',$args);
      

      Otherwise, the "(.*)" will eat up as much as it can, including the "i" if you use the "?" repetition character, since that means 0 or 1.

        In the first case, the expression says "any string possibly followed by an 'i'". "quit" certainly qualifies - it's a string, which doesn't end with an 'i' (which is optional). So the entire string matched is "quit", and the first subpattern (matched by (.*)) is "quit".

        In the second case, the expression says "any string followed by an i". Now the only match is "qui", where "qu" is matched by (.*) and "i" is matched by (i).

          That did it. One more question though is there anyway to include an entire string withing that character class?

          i.e. [hide]

            I tried using negative lookahead but wasn't having much success, so I thought I'd ask. I may be doing things wrong though.

            Here's the code I'm using.
            code=php[/code]

              That's "any string that's not followed by 'hide'". So "blahblahblahhide" succeeds, because "blahblahbla" is a string that's not followed by "hide".

              code*[/code]
              Matches zero or more characters, but before matching each character it checks first that it doesn't start "hide".

                ice, I looked that already...

                I do have a follow up question that maybe you or someone else could helpme with.

                How would I get the everything before and after the 'hide'.

                i.e. Before hide After

                Ideally I want 'Before ' and ' After', please note that 'hide' is optional and may not always be located in the string that's beign searched.

                ice, when your around next time I want to go over something with you. 😉

                  Oh, that's easy.

                  @list($before, $after) = explode('hide', $string, 2);
                  

                  I limit it to 2 because I don't know if $after might have "hide" in it or not. You can check to see if $after isset; if it isn't, then "hide" didn't appear in $string.

                    Weedpacket I am aware of the explode solution but was wondering if there is way to get this accomplished using a regular expression?

                    Thanks again.

                      [man]preg_split[/man]('/hide/', $string); if you're that committed.

                        Sorry for being vague, I should have said using preg_match. I'm trying get a better understanding of regular expressions and am often unsure why something isn't working. By seeing a working example and then comparing it with what I've done it will better help me understand things.

                        Thank you.

                          Here's my results

                          Example 1.

                          preg_match('/(.*?)(?:hide(.*))?/','whyhidethis',$args);
                          print_r($args);
                          
                          // Array( [0] => [1] => )
                          
                          

                          Example 2.

                          preg_match('/(.*?)(?:hide(.*))/','whyhidethis',$args);
                          print_r($args);
                          
                          // Array( [0] => whyhidethis [1] => why [2] => this )
                          
                          

                          Using the code provided results in an empty array, whereas if I modify it to not include '?' it works. That said the 'hide' within the string my not always be there so I would think the code your provided is correct.

                          I so confused when it comes to regular expressions.

                            /((?:(?!hide).)*)(?:hide(.*))?/

                            but it's more important for the code to be legible to humans than for it to use some technology du jour.

                              Write a Reply...