1

I need to capture everything between 'one' and 'four', the 'four' being optional. We don't know what's between 'one' and 'four'. I tried matching it, but not getting the right result. What am I doing wrong?

$text = "one two three four five six seven eight nine ten";
preg_match("~one( .+)(four)?~i", $text, $match);

print_r($match);

Result:

Array ( [0] => one two three four five six seven eight nine ten [1] => two three four five six seven eight nine ten )

Need Result:

Array ( [0] => one two three four five six seven eight nine ten [1] => two three [3] => four)

PS: Yes, the 'four' needs to be optional.

frosty
  • 2,559
  • 8
  • 37
  • 73

2 Answers2

1

Here you need to use alternation operator.

one(( .+)(four).*|.*)

DEMO

Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
0

By default repeat operators (like "?", "*", "+" or {n,m}) are greedy - they wil try to match as much symbols as they can. You can read more on this behalf here: What do lazy and greedy mean in the context of regular expressions?

To make them not greedy add "?" after them. Like this: "~one( .+?)(four)?~i"

Community
  • 1
  • 1
Dmitry
  • 1,263
  • 11
  • 15
  • This is the result after I followed your advice: Array ( [0] => one t [1] => t ) – frosty Nov 12 '15 at 02:15
  • 1) My solution is wrong in terms of it is not going to work if there is no word "four" - group will be empty. 2) Problem with original regex is in greed "+" operator. 3) I think you should use Avinash Raj's solution. As it cover all cases. The only thing you should be aware - if there is several words "four" - if will match until last one, not first. Hope that's what you want. – Dmitry Nov 12 '15 at 02:18