Regex соответствует строке между%

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

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

 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% 

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

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

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

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

Другой вариант – разместить « ? » После точки, которая говорит «не жадничать»:

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

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

Вы делаете жадный матч – используйте ? сделать его неровным:

 /%.*?%/ 

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

 /%.*?%/s 

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

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

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

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

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

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