Какие выражения будут соответствовать шаблону (^[0-9]..[a-zA-Z ]+$) в команде grep? Linux bash

Какие выражения будут соответствовать шаблону (^[0-9]..[a-zA-Z ]+$) в команде grep? Linux bash

Я пытаюсь понять, какие именно выражения регулярное выражение (^[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) о том, что это может на самом деле сделать, см. ниже

Некоторые заметки

  1. В вашем примере вы используете регулярное выражение без кавычек. Это означает, что любые символы открыты для интерпретации оболочкой до того, как они будут переданы команде grep. Если ваш шаблон содержит $или символы подстановки ( *, ?и [...]списки символов!), оболочка может попытаться выполнить расширение переменной (тем самым заменив части вашего RegEx) или расширить шаблоны подстановки в, возможно, несколько имен файлов, так что в итоге у вас будет больше аргументов в командной строке, чем вы изначально предполагали. Другие символы, которые являются специальными для оболочки ( >, #, ;и т. п.), могут привести к еще более неожиданному поведению. Вам следует использовать

    grep -E '^[0-9]..[a-zA-Z]+$' filename.txt
    

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

    grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
    
  2. Списки символов, содержащие диапазоны (например 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

Связанный контент