Команда grep с ls -a не работает должным образом?

Но когда я пытаюсь сохранить вывод во входном файле, он не работает. Входной файл пуст после выполнения команды. Почему?

Потому что > input заставляет оболочку усекать файл перед выполнением команды tr . Кстати, вы можете обойти это с помощью более продвинутой обработки дескрипторов в Bash :

exec 8<>input
exec 9<>input
tr '[A-Z]' '[a-z]' <&8 >&9

exec # <> file открывает файл в дескрипторе # при чтении -Режим записи без усечения.

1
21.08.2018, 04:57
2 ответа

Проблема в том, что вы не заключаете * в кавычки и не заставляете оболочку расширять его перед запуском команды. См .:

$ touch .xau1 .xau2
# this won't work
$ ls -a | grep -i .xau*
# but this does
$ ls -a | grep -i ".xau*"
.xau1
.xau2
# this one too
$ ls -a | grep -i '.xau*'
.xau1
.xau2
# check what shell sees
$ ls -a | grep -i .xau* # now don't press enter but C-x * and you'll see this:
$ ls -a | grep -i .xau1 .xau2
1
27.01.2020, 23:14

Вы страдаете от преждевременного расширения глобуса.

.xa * не расширяется, потому что он не соответствует ничему в текущем каталоге. (Globs чувствительны к регистру.) Однако .x * действительно соответствует некоторым файлам, поэтому он расширяется оболочкой до того, как grep когда-либо его увидит.

Когда grep получает несколько аргументов, предполагается, что первый - это шаблон, а остальные - файлы для поиска этого шаблона.

Итак, в команде ls -a | grep -i .x * , вывод ls игнорируется , а файл ".xsession-errors.old" ищется по шаблону ".xsession-errors ". Неудивительно, что ничего не найдено.

Чтобы этого не произошло, заключите специальные символы в одинарные или двойные кавычки. Например:

ls -a | grep -i '.x*'

Вы также страдаете от путаницы между регулярным выражением и глобусом.

Кажется, вы ищете файлы, которые начинаются с буквальной строки «.x» и сопровождаются чем угодно, но регулярные выражения не работают так же, как файловые глобусы. * в регулярном выражении означает «предыдущий символ ноль или более раз», а не «любая последовательность символов», как в файловых глобусах. Итак, вы , вероятно, хотите:

ls -a | grep -i '^\.x'

Это ищет файлы, имена которых начинаются с буквальных символов «.x» или «.X». На самом деле, поскольку вы указываете только одну букву, вы могли бы так же легко использовать класс символов, а не -i :

ls -a | grep '^\.[xX]'

Дело в том, что регулярные выражения сильно отличаются от файловых глобусов.

Если вы просто попробуете ls -a | grep -i '.x *' , как было предложено, вы будете очень удивлены, увидев, что будет показан КАЖДЫЙ файл! (Тот же вывод, что и ls -a напрямую, за исключением того, что он помещается в отдельные строки, как в ls -a -1 .)

Почему?

Ну, в ] regex (но не в глобусах оболочки), точка (. ) означает «любой отдельный символ». А звездочка ( * ) означает «ноль или более предшествующих символов». Таким образом, регулярное выражение .x * означает «любой символ, за которым следует ноль или более экземпляров символа 'x'».

Конечно, вам не разрешено иметь пустые имена файлов, поэтому каждое имя файла содержит "символ, за которым следует не менее нуля x.":)


Сводка:

Чтобы получить желаемые результаты, вам нужно понимать две вещи:

  1. Специальные символы глобуса без кавычек (включая * , ? , [] и некоторые другие) будут расширены оболочкой до того, как команда, которую вы выполняете, когда-либо увидит их, а
  2. Регулярные выражения отличаются от (и более эффективны, чем) глобусы файлов.
6
27.01.2020, 23:14

Теги

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