В чем разница между * .pl и * .pl в grep? Почему цитирование меняет результат?


10

В чем разница между:
grep "string" . -r --include *.pl

и

grep "string" . -r --include "*.pl"

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


Разница не в grep; это в оболочке. grepникогда не видит цитаты.
Wildcard

Ответы:


17

*(Звезда или звездочка) это специальный символ , который (обычно) интерпретатором , прежде чем он получает команду. Он (обычно) распространяется на все имена файлов, кроме тех, которые имеют начальные точки. Смотрите руководство bash о сопоставлении с образцом для получения дополнительной информации.

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


Примеры объяснил. Цитируемый:

grep "string" . -r --include "*.pl"

Здесь grepбудет получен вариант --includeс аргументом *.pl. Это строка из 4 символов с *первым символом. Что делать grepс этой строкой полностью зависит grep. В этом случае --includeозначает рассматривать только файлы, соответствующие шаблону *.pl.

За кулисами AFAIK GNU grep использует тот же самый шаблон соответствия lib, что и GNU Bash.

Не указано:

grep "string" . -r --include *.pl

Здесь оболочка сначала расширит шаблон *.plдо всех имен файлов, оканчивающихся на .pl. Предположим, есть файлы foo.pl, bar.plи baz.pl. После расширения командная строка выглядит так:

grep "string" . -r --include foo.pl bar.pl baz.pl

Здесь grepбудет получена опция --includeс аргументом foo.pl, за которой следуют опции bar.plи baz.pl. --include foo.plозначает рассматривать только файлы, соответствующие шаблону foo.pl. Так как в шаблоне нет подстановочных знаков, единственный файл, который соответствует файлу с именем foo.pl.

Параметры bar.plи baz.plсредства grep также будут искать в этих файлах, но, поскольку они не соответствуют шаблону, foo.plони будут игнорироваться.


Это отличное наблюдение. Я всегда задавался вопросом, почему grep -rказалось противоречивым, но никогда не замечал, что это было только тогда, когда я использовал *.
j883376

6

Разница в том, что если вы не заключите в кавычку шаблон ( *.pl), он будет расширен оболочкой. Например, если вы запускаете ваш grepкаталог, в котором содержится файл с именем foo.pl, поскольку *plон расширяется оболочкой, то, что на grepсамом деле видит:

grep "string" . -r --include foo.pl

Поскольку вы говорите, что он должен быть включен, foo.plон будет искать только в этом файле.

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

 grep "string" . -r --include *pl

peoplне будет расширен *.pl.
unxnut

@ unxnut хороший момент, ответ отредактирован.
Terdon
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.