PHP preg_match — регулярное выражение неожиданно жадный

Я пытаюсь сопоставить последовательность символов в строке разнесенных букв. Вот несколько примеров:

  • «a b c d e»
  • «C C D E»
  • «б е»
  • «б с е»
  • «е ф г»

Я хочу, чтобы все совпадало с «е», но я также хочу получить два результата для обратных ссылок. Если найдено «b», это должна быть первая обратная ссылка, а вторая должна быть между «b» и «e». Если нет «b», не имеет значения, что такое вторая обратная ссылка. Вот мой тестовый код:

$regex = "( b)?( .*)?? e ";

preg_match("/{$regex}/", " a b c d e ", $matches);

Это возвращает $ совпадения «» (ничего) и «a b c d». Тем не менее, это работает так, как я хочу, если я уберу пробел спереди:

preg_match("/{$regex}/", "a b c d e ", $matches);

Это возвращает $ совпадения «b» и «c d». Бинго! Но мне нужно это начальное пространство в строке сена. Я думал, что (б)? будет жадным из-за? в конце и ожидал (. *) ?? чтобы быть ленивым. Но он предпочитает ленивых (. *) ?? над ним.

Кажется, что первым приоритетом регулярного выражения является совпадение с начала строки, и только ТОГДА учитывают жадность / лень. Это правда?

Вот демонстрация.

В реальном, не упрощенном регулярном выражении может быть несколько (б)? строки, и каждая из них на самом деле является сложным регулярным выражением длиной в десятки символов, поэтому отрицание не будет возможным в (. *) ??.

Что я действительно пытаюсь сделать, так это то, что я хочу, чтобы и первая, и вторая группы были необязательными. Я хочу, чтобы первая группа была жадной, а вторая — жадной. В настоящее время вторая группа переопределяет первую, потому что она может соответствовать ранее в строке.

Есть ли способ изменить регулярное выражение, чтобы выполнить то, что мне нужно?

2

Решение

Вы можете использовать следующее регулярное выражение:

( b)?((?:(?!b).)*)? e

Увидеть демонстрация

Дело в том, что вторая группа не может соответствовать bили он всегда будет «переопределять» первую необязательную группу.

0

Другие решения

Других решений пока нет …