Два жадных квантификатора в одном и том же регулярном выражении
Если у меня есть неизвестная строка структуры:
"stuff I don't care about THING different stuff I don't care about THING ... THING even more stuff I don't care about THING stuff I care about"
Я хочу запечатлеть "вещи, которые меня волнуют", которые всегда будут после последнего появления THING. Существует вероятность появления 0 или более. Если есть 0 вхождений, то мне не о чем беспокоиться. Строка не может начинаться или заканчиваться THING.
Некоторые возможные строки:
"stuff I don't care about THING stuff I care about"
"stuff I don't care about"
Некоторые невозможные строки:
"THING stuff I care about"
"stuff I don't care about THING stuff I don't care about THING"
Мое текущее решение этой проблемы - использовать регулярное выражение с двумя жадными квантификаторами следующим образом:
if( /.*THING(.*)/ ) {
$myStuff = $1;
}
Кажется, это работает, но мой вопрос о том, как два жадных квантификатора будут взаимодействовать друг с другом. Первый (самый левый) жадный квантификатор всегда "более жадный", чем второй?
По сути, я гарантированно не получу раскол, как показано ниже:
"stuff I don't care about THING"
$1 = "different stuff I don't care about THING even more stuff I don't care about THING stuff I care about"
По сравнению с расколом я хочу:
"stuff I don't care about THING different stuff I don't care about THING even more stuff I don't care about THING"
"stuff I care about"
3 ответа
Regex возвращает самый длинный левый матч. Первый подстановочный знак будет сначала совпадать до конца строки, а затем последовательно возвращать символ назад, пока остальная часть регулярного выражения не найдет совпадение, то есть так, чтобы последний THING
в строке совпадает.
В процессе сопоставления .*THING
будет изначально соответствовать всему, вплоть до последнего вхождения THING
Если нет возможности сопоставить остальную часть шаблона, он будет возвращаться назад, становясь короче, и сопоставлять все, вплоть до последнего, кроме одного вхождения THING
и снова попытайтесь выполнить остальную часть шаблона
Однако остальная часть шаблона .*
который всегда будет совпадать, потому что он будет соответствовать пустой строке
Следовательно, .*THING(.*)
будет соответствовать вплоть до последнего вхождения THING
, и будет соответствовать и захватить остальную часть строки
Обратите внимание, что .
будет соответствовать чему угодно, кроме перевода строки. Если в вашем тексте могут быть символы новой строки, вы можете использовать /s
модификатор, чтобы заставить это соответствовать чему-либо вообще
Также обратите внимание, что если шаблон не соответствует (потому что, скажем, нет THING
в строке) тогда $1
останется без изменений. Он по-прежнему будет содержать все, что было установлено при последнем успешном сопоставлении с образцом. Это означает, что вы должны проверить состояние соответствия шаблона, прежде чем использовать значение $1
Вот мой дубль.
/^(?!THING).+THING((?:(?!THING).)+)$/
Принимает строку с 1 или более вхождениями THING. Вещь не может быть в начале или в конце строки. Он получает текст после того, как в последний раз появляется THING.
Редактировать: добавлена проверка "Вещи" в начале строки.
РЕДАКТИРОВАТЬ: Wow, перечитывая ваши спецификации (что я действительно неправильно). Вы сказали, что если есть 0 случаев, то нет ничего, что меня волнует. Строка не может начинаться или заканчиваться THING.
Тогда ваше регулярное выражение в порядке. tripleee
объяснил ситуацию хорошо.