Регулярное выражение не подбирает среднюю группу
Регулярное выражение (PHP):
"/\b(screen|front|glass|lcd)\b.*?\b(not)?\b.*?\b(replaced|cracked|broken|chipped)\b/i"
Цель состоит в том, чтобы регулярное выражение совпадало с обоими:
"screen is not cracked"
"screen is cracked"
и возьмите НЕ, если присутствует как вторая группа. Однако, похоже, что вторая группа пуста для обоих приведенных выше примеров ввода.
Что я делаю неправильно?
Совет: я проверяю это с помощью http://www.regexe.com/
3 ответа
Вы можете поместить первый не жадный квантификатор в необязательную группу со словом "not":
\b(screen|front|glass|lcd)\b(?:.*?\b(not)\b)?.*?\b(replaced|cracked|broken|chipped)\b
Так \b(not)\b
больше не является необязательным внутри группы без захвата, и не жадный квантификатор выполняет свою работу и останавливается, когда достигается "not".
Оптимизированный способ, который лениво захватывает слова до тех пор, пока они не будут взломаны / разбиты / заменены / сломаны и, в конечном итоге, поймут "не":
\b(screen|front|glass|lcd)\W+(?>(?:(not)|\w+)\W+)*?(?=[crb])(c(?:racked|hipped)|replaced|broken)\b
Так как .*?
перед шаблоном, который соответствует необязательному, также не будет соответствовать not
жадно. В этом случае вам нужно использовать негативную перспективу.
(screen|front|glass|lcd)(?:(?!\bnot\b).)*(not)?.*?(replaced|cracked|broken|chipped)
(?:(?!\bnot\b).)*
будет проверять совпадение символа, не будет начальной буквой в строке not
, Если да, то он будет соответствовать следующему символу. Иначе, он не будет соответствовать следующему символу, что приведет к пустому совпадению (из-за*
).
Ты забыл слово "есть"
m!\b(screen|front|glass|lcd)\b *is *\b(not\b)?(replaced|cracked|broken|chipped)\b!i