В Perl квантификаторы в регулярных выражениях — *, +, ?, {n,m} — по умолчанию жадные (greedy): они захватывают максимально возможное количество символов, соответствующее шаблону.
Добавление ? после квантификатора превращает его в ленивый (lazy или non-greedy): он захватывает минимально возможное количество символов, чтобы вся регулярка совпала.
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*>/; # Захватит '<bar> baz <quux>'
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*?>/; # Захватит '<bar>'
Жадное выражение может «съесть» больше, чем ожидаете при парсинге HTML и других вложенных конструкций!
Чем отличаются следующие две регулярки при разборе строки
<a><b><c>:/<(.*)>/и/<(.*?)>/?
Ответ:
/<(.*)>/ (жадная) захватит максимальный блок — совпадение: <a><b><c>/<(.*?)>/ (ленивая) — только первую группу: <a>Пример:
my $s = '<a><b><c>'; $s =~ /<(.*)>/; # $1: 'a><b><c' $s =~ /<(.*?)>/; # $1: 'a'
История
В приложении для импорта новостных заголовков программист хотел распарсить название тега в строке
<title>Новость</title>, используя/\<(.*)\>/. В итоге регулярка захватывала всю строку между<первой и>последней, а не нужный элемент. Ошибку нашли, когда появились вложенные теги.
История
В логическом парсере для выделения quoted strings используемый шаблон
/"(.*)"/неожиданно захватывал всё между первой и последней кавычкой. В результате разметка разбивалась некорректно, пока не заменили шаблон на/"(.*?)"/.
История
В автоматическом парсере CSV с возможностью кавычек был неправильно написан шаблон на "жадность", из-за чего несколько колонок склеивались в одну. Отказ введённого парсера выявился только на больших данных — ленивая модификация шаблона решила проблему.