2013-05-19 3 views
6

У меня есть .net regex, который я тестирую с помощью Windows Powershell. Выход заключается в следующем:Ненадежный квантификатор регулярных выражений дает жадный результат

> [System.Text.RegularExpressions.Regex]::Match("aaa aaa bbb", "aaa.*?bbb") 


Groups : {aaa aaa bbb} 
Success : True 
Captures : {aaa aaa bbb} 
Index : 0 
Length : 11 
Value : aaa aaa bbb 

Мое ожидание, что с помощью ? квантор может вызвать матч будет aaa bbb, как вторая группа из является достаточным, чтобы удовлетворять выражению. Является ли мое понимание не-жадных кванторов ошибочным, или я неправильно тестирую?

Примечание: это явно не та же проблема, как Regular Expression nongreedy is greedy

ответ

5

Это распространенное недоразумение. Леничные квантификаторы не гарантируют кратчайшее совпадение. Они только убеждаются, что текущий квантификатор из текущей позиции не соответствует большему количеству символов, чем необходимо для общего соответствия.

Если вы действительно хотите обеспечить кратчайшее возможное совпадение, вам необходимо сделать это явным. В этом случае это означает, что вместо .*? вы хотите, чтобы подрегрех соответствовал любому, что не является ни aaa, ни bbb. Таким образом, полученное регулярное выражение будет

aaa(?:(?!aaa|bbb).)*bbb 
+0

Я просто сделал то, что должен был сделать в первую очередь, и посоветовался с соответствующей главой Фридла. Это привело меня к «aaa» ((?! Aaa).) * Bbb', что более или менее то, что вы сказали, за исключением того, что ваш ответ содержит дополнительные сведения о том, как сделать невозможным захват подвыражения, а также тесты для bbb в отрицательном смотреть вперед. Хороший ответ. –

5

Сравните результат для строки aaa aaa bbb bbb:

regex: aaa.*?bbb 
result: aaa aaa bbb 

regex: aaa.*bbb 
result: aaa aaa bbb bbb 

Регулярное выражение двигателя находит первое вхождение aaa, а затем пропускает все символы (.*?) до сначала появление bbb, но для жадного оператора (.*) он продолжит поиск большего результата и, следовательно, соответствует las t появление bbb.

+0

Это самое ясное объяснение того, что происходит. +1 – duozmo

0

Ну это очень просто, мы имеем следующую строку

ааа ааа ГЭБ

Давайте посмотрим, у нас есть это регулярное выражение aaa.*?bbb. Движок регулярных выражений будет начинаться с aaa

ааа ааа ГЭБ

движок регулярных выражений имеет в настоящее время .*?bbb. Он приступит к space

ааа пространства ааа ГЭБ

, но мы до сих пор некоторые символы до bbb? Таким образом, регулярное выражение двигатель будет продолжать свой путь и матч второго набора в

ааа ааа пространства ГЭБ

Наконец движок регулярных выражений будет соответствовать bbb:

ааа ааа bbb


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

(?<!^)aaa.*?bbb, это означает, что в соответствии aaa, что не в начале предложения.

Мы также можем использовать aaa(?= bbb).*?bbb, это означает, что оно соответствует aaa, а затем space bbb.

Смотреть это работает 1 - 2.

Только что пришел в чувство, но почему бы вам не использовать aaa bbb?

1

Это не жадная/ленивая проблема. Проблема заключается в том, что ваша строка анализируется слева направо. Когда первый aaa сопоставляется, двигатель регулярных выражений добавляет символы один за другим, чтобы иметь полный шаблон.

Обратите внимание, что с вашим жадным поведением в вашем примере получается тот же результат: первый aaa соответствует, двигатель регулярных выражений принимает все последние символы и возвращает символ по символу до полного совпадения.

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