Почему подстановочный знак работает по-разному при размещении в начале или в конце фразы grep?

Используйте:

REGEXP='^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9-]+$'

Для выбора нужных символов. То, что соответствует [a-z], гарантированно будет [abcdefghijkmnopqrstuvwxyz]только в локали C/POSIX.

(Я предполагаю, что вы не хотите включать обратную косую черту, но это \было ошибочной попыткой избежать-).

Другим вариантом является исправление языкового стандарта C перед использованием инструмента, который оценивает это ^[a-zA-Z0-9-]+$расширенное регулярное выражение (или ^[[:alnum:]-]+$), например:

LC_ALL=C grep -Ee "$REGEXP"

Это допустимо в данном случае, но не в таких случаях, как REGEXP='[A-Z]', если данные для сопоставления с регулярным выражением находятся в кодировке, такой как BIG5 -HKSCS или GB18030 (, и в локалях, которые используют тот же символ ), где многие символы имеют кодировку, содержащую ту же кодировку, что и A-Z.

Пример, где [A-Z]соответствуетÁ(U+00C1,кодируется как 0x88 0x57 в BIG5 -HKSCS (, где 0x57 такжеW)):

$ LC_ALL=zh_HK.big5hkscs REGEXP='[A-Z]' bash -c 'printf "\uc1\n" |
    LC_ALL=C grep -qe "$REGEXP" && echo match'
match
0
08.01.2020, 20:29
1 ответ
$ ls *.txt

Эта команда будет использовать подстановку оболочки для вывода списка всех файлов, имена которых заканчиваются на .txt.

$ ls | grep "*.txt"

Эта команда выведет список всех (не-скрытых )файлов в текущем рабочем каталоге и отправит эти выходные данные в grep, где имена файлов будут сопоставляться с регулярным выражением /*.txt/.

/*.txt/

Это регулярное выражение может (в зависимости от того, какая разновидность регулярных выражений используется )соответствовать шаблону:

*    -- zero or more characters of any type (or possibly only a literal '*'), followed by
.    -- exactly one character of any type, followed by 
txt  -- the literal string 'txt', followed by anything

В регулярных выражениях *является подстановочным знаком, обозначающим «ноль или более предшествующих подвыражений»; но он работает иначе, чем подстановочные знаки оболочки. Соответственно, .не является периодом; это подстановочный знак для одного символа (, аналогичный подстановочному знаку ?в глобах оболочки ). Таким образом, это выражение будет (снова, в зависимости от того, какой вариант регулярного выражения )соответствует любому из file.txt, sometxtfile, photo_of_a_txt_file.png, но на самом деле не txtfile(, так как нет совпадения для одного символа передtxt). Важно знать, что литеральная строка txtпоэтому может появиться где угодно, но не в самом начале имени файла с этим регулярным выражением.

Лучшее регулярное выражение для перехвата имен файлов, оканчивающихся на .txt, было бы/\.txt$/:

\.  -- A literal.
txt -- The literal string 'txt'
$   -- End of input

Поэтому, если вы настаиваете на передаче lsвgrep(и давайте пока не будем углубляться в книги, в которых можно было бы написать, почему синтаксический анализ вывода ls— плохая идея ), вы, вероятно, имеете в виду это:

$ ls | grep "\.txt$"

Что касается последующего использования wc, вам не нужно этого делать. grepумеет считать:

$ ls | grep -c "\.txt$"
2
28.01.2020, 02:29

Теги

Похожие вопросы