*
имеет особое значение как в качестве символа для подстановки оболочки («подстановочный знак»), так и в качестве метасимвола регулярного выражения . Вы должны принять во внимание и то и другое, хотя, если вы заключите в кавычки свое регулярное выражение, вы можете помешать оболочке обработать его специально и убедиться, что оно передает его без изменений grep
. Хотя это похоже на концептуально, что *
означает для оболочки весьма отличается от того, что это значит grep
.
Сначала оболочка рассматривается *
как подстановочный знак.
Вы сказали:
Независимо от того, заключено ли выражение в кавычки, не имеет значения.
Это зависит от того, какие файлы существуют в любом каталоге, в котором вы оказались при запуске команды. Для шаблонов, которые содержат разделитель каталогов /
, это может зависеть от того, какие файлы существуют во всей вашей системе. Вы всегда должны заключать в кавычки регулярные выражения для grep
- и одинарные кавычки обычно лучше - если вы не уверены, что у вас все в порядке с девятью типами потенциально удивительных преобразований, которые оболочка выполняет перед выполнением grep
команды.
Когда оболочка сталкивается с *
символом, который не заключен в кавычки , он принимает значение «ноль или более любого символа» и заменяет содержащее его слово на список имен файлов, соответствующих шаблону. (Имена файлов , которые начинаются с .
исключены - если ваш шаблон сам по себе не начинается с .
или . Вы настроили свою оболочку в любом случае , чтобы включить их) Это известный как подстановка --и также и имена расширения имен файлов и имен файлов .
Эффект с grep
обычно состоит в том, что первое подходящее имя файла принимается как регулярное выражение - даже если для читателя-человека будет совершенно очевидно, что оно не подразумевается как регулярное выражение - в то время как все остальные имена файлов перечислены автоматически из вашего glob - это файлы, внутри которых можно искать совпадения. (Вы не видите список - он передается непрозрачно grep
.) Вы практически никогда не хотите, чтобы это произошло.
Причина этого иногда не проблема - и в вашем конкретном случае, по крайней мере , до сих пор , это wasn't - это то , что *
останется в одиночестве , если все следующие условия :
Там не было ни одного файла , чьи имена совпадают. ... Или вы отключили глобирование в своей оболочке, как правило, с помощью set -f
или эквивалентного set -o noglob
. Но это необычно, и вы, вероятно, знаете, что сделали это.
Вы используете оболочку, чье поведение по умолчанию - оставить *
один, когда нет подходящих имен файлов. Это тот случай в Bash, который вы, вероятно, используете, но не во всех оболочках в стиле Борна. (Поведение по умолчанию в популярной оболочке Zsh, например, для глобусов либо (а) раскрывает, либо (б) выдает ошибку.) ... Или вы изменили это поведение вашей оболочки - как это делается, варьируется через снаряды.
В противном случае вы не указали своей оболочке разрешать замену глобусов ничем, когда не найдено подходящих файлов, или сообщать об ошибке в этой ситуации. В Bash это можно было бы сделать, включив параметр nullglob
или failglob
shell соответственно.
Иногда вы можете положиться на № 2 и № 3, но вы редко можете положиться на № 1. grep
Команда с некотируемым рисунком , который работает в настоящее время может перестать работать , если у вас есть разные файлы или при запуске его из другого места. Процитируйте свое регулярное выражение, и проблема исчезнет.
Тогда как grep
команда рассматривает *
как квантор.
Другие ответы - такие, как Сергей Колодяжный и Кос - также касаются этого аспекта этого вопроса, несколько по-другому. Поэтому я призываю тех, кто их еще не читал, делать это либо до, либо после прочтения оставшейся части этого ответа.
Предполагая, что это *
действительно делает grep - что должно обеспечить цитирование - grep
затем подразумевает, что элемент, предшествующий ему, может встречаться любое количество раз , вместо того, чтобы встречаться ровно один раз . Это все еще может произойти один раз. Или это может вообще не присутствовать. Или это может быть повторено. Текст, который соответствует любой из этих возможностей, будет сопоставлен.
Что я имею в виду под «предметом»?
Единый персонаж . Так b
матчи буквальный b
, b*
соответствует нулю или более b
S, таким образом , ab*c
соответствует ac
, abc
, abbc
, abbbc
и т.д.
Аналогично, так как .
соответствует любому символу , .*
соответствует нулю или более символов 1 , при этом a.*c
совпадения ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, даже acccccchjckhcc
, и т.д. Или
Классовый характер . Так как [xy]
спички x
или y
, [xy]*
соответствует нулю или более символов , где каждый из них является либо x
или y
, таким образом , p[xy]*q
соответствует pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
и т.д.
Это также относится и к обсчитывать формы классов персонажей , как \w
, \W
, \s
и \S
. Так как \w
соответствует любому символу слова, \w*
соответствует нулю или более символов слова. Или
Группа . Так как \(bar\)
матчи bar
, \(bar\)*
соответствует нулю или более bar
лет, таким образом , foo\(bar\)*baz
соответствует foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
и т.д.
С опциями -E
или -P
, grep
ваше регулярное выражение обрабатывается как ERE или PCRE соответственно, а не как BRE , и затем группы окружаются (
)
вместо \(
\)
, так что тогда вы будете использовать (bar)
вместо \(bar\)
и foo(bar)baz
вместо foo\(bar\)baz
.
man grep
дает достаточно доступное объяснение синтаксиса BRE и ERE в конце, а также перечисляет все параметры командной строки, grep
принимаемые в начале. Я рекомендую эту страницу руководства в качестве ресурса, а также документацию по GNU Grep и этот учебный / справочный сайт (на который я ссылаюсь на несколько страниц выше).
Для тестирования и обучения grep
я рекомендую называть его шаблоном, но без имени файла. Затем он принимает данные от вашего терминала. Введите строки; Отраженные вам строки - это те строки, которые содержали текст, соответствующий вашему шаблону. Чтобы выйти, нажмите Ctrl+ Dв начале строки, которая сигнализирует о конце ввода. (Или вы можете нажать Ctrl+, Cкак и в большинстве программ командной строки.) Например:
grep 'This.*String'
Если вы используете --color
флаг, grep
то выделите определенные части ваших строк, которые соответствуют вашему регулярному выражению, что очень полезно как для выяснения того, что делает регулярное выражение, так и для поиска того, что вы ищете, как только вы это сделаете. По умолчанию пользователи Ubuntu имеют псевдоним Bash, который grep --color=auto
запускается - что достаточно для этой цели - при запуске grep
из командной строки, поэтому вам, вероятно, даже не нужно проходить --color
вручную.
1 Следовательно, .*
в регулярном выражении означает, что *
означает в глобусе оболочки. Однако различие заключается в том, grep
что в любом месте автоматически печатаются строки, содержащие ваше совпадение , поэтому обычно нет необходимости иметь .*
начало или конец регулярного выражения.
* != any number of unknown characters
читать документ.)