2009-08-13 3 views
3

Я пытаюсь совместить подстроки, которые заключены в%, но preg_match_all, кажется, содержит несколько одновременно в той же строке.Regex соответствует строке между%

код выглядит следующим образом:

preg_match_all("/%.*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
print_r($matches); 

который производит следующий вывод.

Array 
(
    [0] => Array 
     (
      [0] => %hey%_thereyou're_a%rockstar% 
      [1] => %there% 
     ) 

) 

Однако я хотел бы, чтобы произвести следующий массив вместо:

[0] => %hey% 
[1] => %rockstar% 
[2] => %there% 

Что мне не хватает?

ответ

12

Заменить «.» в своем регулярном выражении с «[^%]„:

preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

Что происходит в том, что“.» является «жадностью» соответствие, насколько это возможно, может, в том числе все вверх до конечного% на линии. Замена его на отрицательный класс символов «[^%]» означает, что он будет соответствовать чему-либо , за исключением процентов, что позволит ему соответствовать только битам, которые вы хотите.

Другим вариантом было бы поместить «?» после того, как точка, которая говорит, что «не жадничать»:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

В приведенном выше примере, любой вариант будет работать, однако Есть моменты когда вы можете искать что-то большее, чем один символ, поэтому отрицательный класс символов не поможет, поэтому решение заключается в не-greedify совпадении.

+0

Это работает. Благодаря! – Spoike

4

Вы делаете жадного матч - использовать ?, чтобы сделать его ungreedy:

/%.*?%/ 

Если символ новой строки может произойти в матче, добавьте с (DOTALL) Модификатор:

/%.*?%/s 
1

Причина в том, что звезда жадная. То есть, звезда заставляет двигатель регулярного выражения повторять предыдущий токен как можно чаще. Ты должен попытаться .*? вместо.

1

Вы можете попробовать /%[^%]+%/ - это означает, что между знаками процента вы хотите только совместить символы, которые не являются знаками процента.

Вы также можете сделать рисунок неровным, например. /%.+%/U, поэтому он будет захватывать как можно меньше (я думаю).

+0

Точнее, '/ U' инвертирует жадность всех кванторов в регулярном выражении, поэтому' /%.+%/ U' совпадает с '/%.+?%/' и '/%.+?%/U' совпадает с '/%.+%/'. http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php –

2

Добавить? после *:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
1

|% (\ w +)% | Это будет работать именно так, как вы хотите.

Смежные вопросы