жадные и ленивые регулярные выражения (вопрос понимания)

Я преподаю себе регулярные выражения, и я застрял в «жадных» и «ленивых» повторах.

То, что я выяснил до сих пор, это то, что

  • «Жадный» означает, что RegExp ищет как можно больше совпадений, где
  • «Ленивый» означает, что RegExp ищет как можно меньше совпадений

Большинство статей, которые я нашел, касаются: а) использования его на языке программирования, в то время как я застрял здесь с grep и egrep или b) использовал grep -P для активации Perl Mode ; но поскольку у меня нет никаких знаний о Perl, это не очень полезно для меня.

Мой вопрос о понимании : я пришел к этому методу кувалды:

  • ленивые повторы будут искать кратчайшее совпадение
  • если результаты слишком велики, → снимите репитер с помощью ?
  • если результаты еще слишком длинные → найдите другое решение

Это то, что я смог выяснить из примеров и экспериментов с кодом HTML, где я получил некоторые, но не подавляющие результаты.

Я был бы признателен, если бы кто-нибудь мог сказать мне, если и где я пропустил некоторые важные моменты с моим резюме.

Это не кратчайший матч, просто короткий матч. Жадный режим пытается найти последнее возможное совпадение, ленивый режим – первое возможное совпадение. Но первое возможное совпадение не обязательно является самым коротким.

Возьмите входную строку foobarbaz и regexp o.*a foobarbaz (жадный) или o.*?a foobarbaz (ленивый).

Минимальное совпадение в этой входной строке будет oba .

Однако RegExp ищет совпадения слева направо, поэтому o находит первый o в foobarbaz . И если оставшаяся часть шаблона создает совпадение, это то, где он остается.

После первого o obarbaz .* (Жадный) ест obarbaz (вся строка), а затем возвращается назад, чтобы соответствовать остальной части рисунка ( a ). Таким образом, он находит последний a в baz и заканчивает совпадение oobarba .

После первых o .*? (ленивый) не ест всю строку, вместо этого он ищет первое появление остальной части шаблона. Итак, сначала он видит второй o , который не соответствует a , тогда он видит b , который не соответствует a , а затем видит a , который соответствует a , и потому что он ленив, и там он останавливается. (и результат ooba , но не oba )

Так что, хотя это не кратчайший, он короче, чем жадная версия.

«Режим Perl» относится к perl-совместимым регулярным выражениям (PCRE). Говоря по-разному , это стиль регулярного выражения, используемый изначально большинством современных языков, если у них есть встроенные собственные регулярные выражения – Perl, Python, Ruby, PHP, JavaScript, Java – хотя между ними могут быть небольшие различия; технически PCRE получен, но не идентичен движку perl regexp и т. д., но если вы можете использовать регулярные выражения на одном из этих языков, то они на 99% одинаковы для остальных. Он преобладает там, где это опция, потому что это улучшение в более старом стиле, которое теперь отличается как POSIX-регулярное выражение, которое является стандартным для старых школьных инструментов, таких как grep.

Не жадный, ака. ленивый модификатор не имеет значения в контексте использования grep для соответствия строк. Это связано с тем, что не может быть полной строки, которая соответствует ленивому выражению, которое жадный не будет соответствовать, и наоборот. Однако вы можете увидеть разницу, если вы используете ключ -o , который отображает согласованное содержимое сегмента, а не целые строки (это немного отличается от того, что делает --color ):

 »echo "123 abc 456 def 789" > eg.txt »grep -o -P "(\d+\s[A-Za-z]+\s)+" eg.txt 123 abc 456 def »grep -o -P "(\d+\s[A-Za-z]+\s)+?" eg.txt 123 abc 456 def »grep -o -P "\d+\s[A-Za-z]+\s\d+" eg.txt 123 abc 456 »grep -o -P "\d+\s[A-Za-z]+\s\d+?" eg.txt 123 abc 4 56 def 7 

Если вы используете grep таким образом (с -o ), то жадность имеет значение. Если вы используете grep для соответствия строкам, содержащим шаблон, не жадным ? не имеет значения, так или иначе.

Короче: жадный матч соответствует как можно большему, не-жадный матч соответствует как можно меньше.