Проблема с отображением каталога в grep

grep кажется сломанным на моей машине. Переустановка не помогает. Перезагрузка не помогает. Первые две строки создают файл, содержащий произвольный текст, а ввод завершается символом control-D.

ls -1 означает список в одном столбце. Пример следует ...

> cat > file0.txt
asdf
> cp file0.txt file1.txt
> ls -1
file0.txt
file1.txt
> ls -1 | grep f*
> 

Прежде чем столкнуться с этой проблемой, я допустил ошибку, вызвав grep с непревзойденной цитатой, но я не понимаю, как эта проблема может пережить перезагрузку.

Пример непревзойденной цитаты ...

ls -1 | grep 'file* | wc

В этом примере список каталогов передается по каналу grep, который передает в программу счетчика строк, слов и байтов wc.

4
задан 7 September 2019 в 11:38

4 ответа

grep не использовал вывод ls всегда.

Когда Вы работаете grep f* в ситуации, где Ваша оболочка расширяется f* к двум или больше аргументам, grep полагает, что все кроме одного из них как названия файлов открываются и читают. Когда grep чтения из именованных файлов, его поведение по умолчанию чтения из стандартного входа не применяется, таким образом, это не считывает данные, переданные по каналу в него от другой команды.

Ваш grep программа не повреждается, и поведение, которое Вы наблюдали, является корректным и ожидаемым поведением, которое является почему переустановка grep и перезагрузка не изменила его. Детали следуют.

grep f* не передал аргумент f* к grep.

grep никогда не видел текст f*. Как Soren A говорит, f* шарик. Шарики рассматривает особенно Ваша оболочка. Поскольку f* не был заключен в кавычки, оболочка развернула его на названия файлов в текущем каталоге, которые запускаются с f. Каждое такое имя было передано grep как отдельный аргумент. (Этот вид расширения оболочки известен по-разному как globbing, расширение имени файла и расширение пути.)

На основе Вашего описания существует точно два файла, которые соответствуют f* шарик: file0.txt и file1.txt. Так как это - эти только два файла в текущем каталоге, имена которого запускаются с f, параметры командной строки передали grep от выполнения grep f* точно то же как переданные ему от выполнения grep file0.txt file1.txt. Если необходимо было добавить больше таких файлов к каталогу, то grep f* передал бы больше, чем те два имен файлов как аргументы grep, но file0.txt и file1.txt был бы все еще включен среди них.

Вы передали по каналу ls вывод к grep, но grep не читал из канала.

Канал соединяет стандартный вывод одной команды к стандартному входу другого. Как cat и много других команд, grep принимает вход двумя способами:

  1. Можно передать его имена файлов как параметры командной строки, и это будет читать из тех файлов. Первый аргумент неопции grep шаблон, но последующие аргументы неопции рассматривают как имена файлов, от которых будет взят вход.

    (Вы не пытаетесь передать несколько шаблонов grep, но если бы Вы были, то Вы могли бы использовать -e опция, операнд которой всегда рассматривают как шаблон.)

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

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

    (Вы не пытаетесь вызвать grep для чтения стандартного входа в дополнение к одному или нескольким именованным файлам, но если Вы были, Вы могли бы передать его - аргумент.)

Поскольку у Вас есть два файла в текущем каталоге, имена которого запускаются с f, шарик f* расширяется до двух аргументов. Первое, file0.txt, используется в качестве шаблона. Второе, file1.txt, взят для именования входного файла. Поскольку grep дан аргумент, указывающий входной файл, первая из этих двух ситуаций, описанных выше, применяется ("Можно передать его имена файлов как параметры командной строки"). Так grep никогда чтения от стандартного входа и никогда не используют вывод ls.

11
ответ дан 23 November 2019 в 11:34

Выражение grep f* в Вашем случае, будет расширен до grep file0.txt file1.txt оболочкой.

По-видимому, нет никакой строки с file0.txt в файле file1.txt.

Я знаю, что это не то, что Вы хотели, но это, как это работает.

:~$ mkdir test
:~$ cd test/
:~/test$ touch f1
:~/test$ touch f2
:~/test$ set -x
:~/test$ ls | grep f* 
+ ls --color=auto
+ grep --color=auto f1 f2
14
ответ дан 23 November 2019 в 11:34
ls | grep 'f*'

плохая форма.

ls f*

должен быть предпочтен.

При использовании более сложных regex шаблонов переключитесь на egrep/grep -E.

В то время как я здесь, cat редко необходим. tac 100x более полезен, чем cat. cat злоупотребление является серьезной проблемой о подобных Unix системах.;)

0
ответ дан 23 November 2019 в 11:34

* специальный символ, который свободно интерпретируется как новая команда / инструкция. Вы хотите поместить a \ перед ним:

ls -1 | grep f\*

Однако то, что Вы, вероятно, хотите, должно получить все файлы, запускающиеся с f вместо ВСЕХ файлов, содержащих f так используйте другой специальный символ вместо этого:

ls -1 | grep ^f

^ дает grep команду находить строки, запускающиеся с f.

0
ответ дан 23 November 2019 в 11:34

Другие вопросы по тегам:

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