Неожиданное поведение grep в bash относительно строк, которым предшествуют несколько одинаковых символов - PullRequest
0 голосов
/ 27 июня 2019

Я играю бандит из overthewire.org ; Чтобы добраться до уровня 10 , требуется, чтобы я нашел строки, перед которыми стоят несколько символов "=" (знак равенства) (я интерпретировал "несколько" как "два или более") в текстовом файле.

Целевые строки выглядят следующим образом:

========== passwordhere123

т.е. десять знаков равенства, один пробел и строка букв и цифр, за которой следует разрыв строки (неукажите, какой именно тип).

Эти строки следует исключить:

c========== EqualSignDidNotStartLine

= only-one-equal-sign

equalsign=somewhereElse

No equal signs at all

Исходные данные не содержали каких-либо строк, которым предшествовало бы меньше десяти, но больше чем один =;в тексте есть несколько + (плюсиков), но + и = никогда не находятся в одной строке.

Бандитский сервер работает под управлением linux @ 4.18.12 (uname-r), GNU bash 4.4 (с man-страницы) и GNU grep 2.27 (с man-страницы).

Необработанные данные содержат нечитаемые части, поэтому они передаются через strings первыми, чтобы оставить толькопонятные человеку строки для обработки grep.

Из того, что я узнал, стандартный механизм регулярных выражений grep (BRE, спасибо Casimir ) не должен слишком отличаться от PCRE.* все еще является квантификатором (соответствует предыдущему шаблону ноль или более раз), а не автономным шаблоном, означающим «все, ноль или более раз».Это смущает меня в поведении grep ниже.

Редактировать: за этот график , "+" необходимо экранировать (т. Е. \+) в BRE.Это не помогает, хотя.Я сделаю еще несколько тестовых строк, чтобы попытаться расшифровать происходящее.

Вот команда, которую я попробовал:

strings data.txt | grep -P -e ^==+.*

strings data.txt | grep -P -e ^==+.*$ #both PCRE expressions worked correctly

#start BRE

strings data.txt | grep -e ^==.*    #includes every line preceded by at least two =; works

strings data.txt | grep -e ^==.*$   #includes every line preceded by at least two =; works

strings data.txt | grep -e ^==+.*   #no output; why?

strings data.txt | grep -e ^==+.*$  #no output

strings data.txt | grep -e ^==+*    #includes every target line, so works; WHY IS THIS A LEGAL REGEX?

strings data.txt | grep -e ^==+*$   #no output

strings data.txt | grep -e ^==\+.*  #no output

strings data.txt | grep -e ^==\+.*$ #no output

strings data.txt | grep -e ^==\+*   #includes every target line, so works

strings data.txt | grep -e ^==\+*$  #no output

1 Ответ

1 голос
/ 27 июня 2019

Во-первых, я бы беспокоился о расширении оболочки. Исходя из большого опыта, я помещал регулярные выражения в командной строке в «одинарные кавычки», чтобы избежать безумия метасимволов.

Во-вторых, это (под BRE):

^==+*

совершенно правильно. Это значит:

^     anchored at the start of the input
==    followed by 2 '=' charaters
+*    followed by 0 or more '+' characters 

Вы заявили "Из того, что я узнал, стандартный механизм регулярных выражений grep (BRE, спасибо Casimir) не должен слишком сильно отличаться от PCRE" , и я думаю, что это ваша проблема. В частности, + является метасимволом в PRCE, но не в BRE. Обратите внимание:

echo '==+++++' | grep ^==+*
==+++++

echo '==+++++' | grep -E ^==+*
grep: repetition-operator operand invalid

-E на grep включает расширенное регулярное выражение.

Итак, теперь, когда вы знаете, что + - это буквально + в BRE, вы можете понять, почему все ваши паттерны ведут себя так же, как и они?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...