Я пытаюсь понять, какие именно выражения регулярное выражение (^[0-9]..[a-zA-Z ]+$)
обнаруживает в grep
команде (терминал Linux)
Я знаю, что если бы я написал следующую команду:
grep ^[0-9]..[a-zA-Z] filename.txt
Я обнаружу любую строку, содержащую выражения, такие как 92afg
Но я не уверен, что они +$
означают и какие выражения я смогу обнаружить с помощью команды
grep ^[0-9]..[a-zA-Z]+$ filename.txt
Я попытался открыть новый текстовый файл и просто ввести выражения, которые, как я думал, будут обнаружены, но ни одно из них не совпало, поэтому я был бы признателен за объяснение этого.
решение1
Давайте разберемся. Прежде всего, обратите внимание, что этот RegExp использует«Расширенное регулярное выражение»синтаксис (ERE) — +
это метасимвол, который не работает в синтаксисе «Базового регулярного выражения», который grep
используется по умолчанию (то есть он будет соответствовать самому себе и потребует литерала +
в этой позиции), поэтому, если вы хотите использовать это регулярное выражение с grep
, вам нужно будет передать эту -E
опцию.
- — это
^
якорь, который связывает данную позицию регулярного выражения с началом строки. - Это
[0-9]
список символов, который будет соответствовать любому одиночному (1) символу, попадающему в диапазон сортировки между0
и9
. Что именно он содержит, зависит от «порядка сортировки», определяемого, среди прочего, переменной окруженияLC_COLLATE
. - Соответствует
.
любому отдельному символу, поэтому два..
означает «любые два символа». - Снова
[a-zA-Z]
— это список символов, который будет соответствовать символам (1) , которые попадают междуa
иz
, а также тем, которые попадают междуA
иZ
. Опять же, что это значит, зависит от порядка сортировки! - Означает
+
«один или несколько из предыдущих» - — это
$
якорь, который связывает данную позицию регулярного выражения с концом строки.
Итак, ваш RegExнамеревается(1) сопоставьте любые строки, которые
- начинаться с любой цифры
- за которыми следуют любые два символа
- и содержать только буквы (но не менее одной) до конца строки.
(1) о том, что это может на самом деле сделать, см. ниже
Некоторые заметки
В вашем примере вы используете регулярное выражение без кавычек. Это означает, что любые символы открыты для интерпретации оболочкой до того, как они будут переданы команде
grep
. Если ваш шаблон содержит$
или символы подстановки (*
,?
и[...]
списки символов!), оболочка может попытаться выполнить расширение переменной (тем самым заменив части вашего RegEx) или расширить шаблоны подстановки в, возможно, несколько имен файлов, так что в итоге у вас будет больше аргументов в командной строке, чем вы изначально предполагали. Другие символы, которые являются специальными для оболочки (>
,#
,;
и т. п.), могут привести к еще более неожиданному поведению. Вам следует использоватьgrep -E '^[0-9]..[a-zA-Z]+$' filename.txt
Вместо этого. Обратите внимание, что вы можете избавиться от открывающих и закрывающих якорей, используя
-x
флаг для принудительного сопоставления "целой строки":grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
Списки символов, содержащие диапазоны (например
a-z
, ), являютсяопасныйпотому что они могут не дать вам того, что вы думаете. Наивно можно было бы ожидать, что они будут соответствовать всем символам, которые находятся между начальным и конечным символом в таблице ASCII, но это верно только для локалиC
. В других локалях (и в частности в обычно установленных системных локалях, таких какen_US.UTF-8
) порядок сортировки примерно такой,aAbB ... zZ
поэтомуa-z
также будет соответствовать большинству заглавных букв. Кроме того, соответствие на самом деле не на уровне отдельных символов, а на уровне «элементов сортировки», что означает в некоторых локалях, дажекомбинации из нескольких буквможет совпадать (например,dzs
в венгерском)! Смотритеэтот ответ(или, в общем, большинство ответов @Stéphane Chazelas о сопоставлении с образцом) для большего понимания. Если вы хотите убедиться, что ваши диапазоны работают, установите порядок сортировки по крайней мере для данной команды черезLC_COLLATE="C" grep -E ' ... ' filename.txt
решение2
+
означает "одно или несколько повторений предыдущего", $
это "конец строки". Обратите внимание на разницу по сравнению с *
with означает "ноль или несколько повторений".
По сути, это означает: любая строка, начинающаяся с цифры, за которой следуют два любых символа, а затем одна или несколько (возможно, заглавных) букв¹ до конца строки.
(¹ будьте осторожны, в некоторых локалях могут быть не только 26 букв, которые вы ожидаете увидеть в AZ или az, например, è
или ŷ
в зависимости от языка)
Для хорошего руководства по регулярным выражениям я настоятельно рекомендуюпрекрасный сайт grymoire, который я также искренне рекомендую, например, sed
и awk
.
Почему не совпадает?
+
является частью расширенных регулярных выражений (и в противном случае интерпретируется как буквальный +
знак).
Поэтому для использования +
в качестве «одного или нескольких повторений» используйте флаг -E
- grep
и заключите регулярное выражение в кавычки, чтобы избежать проблем со специальными символами оболочки:
grep -E '^[0-9]..[a-zA-Z]+$' filename.txt