*имеет особое значение как в качестве символа для подстановки оболочки («подстановочный знак»), так и в качестве метасимвола регулярного выражения . Вы должны принять во внимание и то и другое, хотя, если вы заключите в кавычки свое регулярное выражение, вы можете помешать оболочке обработать его специально и убедиться, что оно передает его без изменений 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*соответствует нулю или более bS, таким образом , 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читать документ.)