Нежадное сопоставление с grep

Нежадное сопоставление, насколько мне известно, не является частью базового регулярного выражения (BRE) и расширенного регулярного выражения (ERE). Однако поведение в разных версиях grep (BSD и GNU), кажется, предполагает иное.

Например, возьмем следующий пример. У меня есть строка, говорящая:

string="hello_my_dear_polo"

Используя GNU grep:

Ниже приведены несколько попыток извлечь hello из строки.

Попытка BRE (неудачная) :

$ grep -o "hel.*\?o" <<< "$string"
hello_my_dear_polo

Вывод дает целую строку, которая предполагает, что нежадный квантификатор не работает с BRE. Обратите внимание, что я экранировал только ?, поскольку * не теряет своего значения и не требует экранирования.

Попытка ERE (неудачная) :

$ grep -oE "hel.*?o" <<< "$string"
hello_my_dear_polo

Включение опции -E также дает тот же результат, предполагающий, что нежадное сопоставление не является частью ERE. Здесь не было необходимости в экранировании, поскольку мы используем ERE.

Попытка PCRE (успешна) :

$ grep -oP "hel.*?o" <<< "$string"
hello

Включение опции -P для PCRE предполагает, что нежадный квантификатор является его частью, и, следовательно, мы получаем желаемый результат hello. Здесь не было необходимости в экранировании, поскольку мы используем PCRE.

Используя BSD grep:

Вот несколько попыток извлечь hello из строки.

Попытка BRE (неудачная) :

$ grep -o "hel.*\?o" <<< "$string"

Используя BRE, я не получаю вывода от BSD grep.

Попытка ERE (успешна) :

$ grep -oE "hel.*?o" <<< "$string"
hello

После включения опции -E я удивлен, что смог извлечь желаемый результат. У меня вопрос о результатах этой попытки.

Попытка PCRE (неудачная) :

$ grep -oP "hel.*?o" <<< "$string"
usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
    [-e pattern] [-f file] [--binary-files=value] [--color=when]
    [--context[=num]] [--directories=action] [--label] [--line-buffered]
    [--null] [pattern] [file ...]

Использование опции -P дало мне ошибку использования, чего и следовало ожидать, поскольку опция BSD grep не поддерживает PCRE.

Итак, у меня вопрос: почему использование ERE в BSD grep дает правильный результат с использованием нежадного квантификатора, но не с GNU grep.

Это ошибка, недокументированная функция BSD egrep или мое неправильное понимание вывода?


person jaypal singh    schedule 04.05.2014    source источник
comment
В этом случае вы можете использовать hel[^o]*o.   -  person Gumbo    schedule 04.05.2014
comment
Спасибо @Gumbo за ваш комментарий. Я согласен, можно использовать предложенный вами подход для решения проблемы, однако мой вопрос касается странного поведения grep в BSD с включенной опцией -E.   -  person jaypal singh    schedule 04.05.2014


Ответы (1)


Двойной квантификатор - это просто синтаксическая ошибка, которая может привести либо к сообщению об ошибке, либо к неопределенному поведению. Возможно, было бы лучше, если бы вы получили сообщение об ошибке.

Расширения Perl для регулярных выражений POSIX после даты выпуска с большим отрывом; в то время, когда были написаны эти инструменты, было крайне маловероятно, что кто-то попытается использовать этот дурацкий синтаксис для чего-либо. Жадное сопоставление было введено только в Perl 5 в середине 1990-х годов.

person tripleee    schedule 04.05.2014
comment
Спасибо @tripleee. Сообщение об ошибке, вероятно, имело бы больший смысл. Однако оба варианта grep не показывают ошибок и ничего не задокументированы на странице руководства. Я использую grep (BSD grep) 2.5.1-FreeBSD версию, и на странице руководства указано, что последний раз она обновлялась July 28, 2010. Эта страница, похоже, подтверждает, что BSD на 100% совместима с GNU. - person jaypal singh; 04.05.2014
comment
Да, но соответствующие стандарты не сильно изменились с начала 2000-х годов, когда Perl все еще оставался основным поставщиком синтаксиса регулярных выражений Perl. - person tripleee; 04.05.2014