Если я grep документ, который содержит следующее:
ThisExampleString
... для выражения This*String
или *String
ничего не возвращается. Однако This*
возвращает вышеуказанную строку, как и ожидалось.
Независимо от того, заключено ли выражение в кавычки, не имеет значения.
Я думал, что звездочкой указано любое количество неизвестных символов? Почему это работает, только если это в начале выражения? Если это предполагаемое поведение, что я использую вместо выражений This*String
и *String
?
command-line
bash
grep
regex
Trae
источник
источник
* != any number of unknown characters
читать документ.)Ответы:
Звездочка в регулярных выражениях означает «соответствовать предыдущему элементу 0 или более раз».
В вашем конкретном случае
grep 'This*String' file.txt
вы пытаетесь сказать: «Привет, grep, сопоставь мне словоThi
, затем строчныеs
ноль или более раз, а затем словоString
». Строчных буквs
нигде нетExample
, поэтому grep игнорируетThisExampleString
.В случае
grep '*String' file.txt
, если вы говорите «grep, сопоставьте мне пустую строку - буквально ничего - предшествующую словуString
». Конечно, это не так, какThisExampleString
предполагается читать. (Существуют и другие возможные значения - вы можете попробовать это с-E
флагом и без него, но ни одно из значений не имеет ничего общего с тем, что вы действительно хотите здесь.)Зная , что
.
означает «любой символ», мы могли бы сделать это:grep 'This.*String' file.txt
. Теперь команда grep будет читать его правильно:This
за ним следует любой символ (воспринимается как выделение символов ASCII), повторяемый любое количество раз, а затемString
.источник
*
это специальный символ, и его следует заключать в кавычки или экранировать, например, так:grep 'This*String' file.txt
или this:grep This\*String file.txt
чтобы не удивляться неожиданным результатам.*
подстановочный знак. В grep*
это оператор регулярного выражения. См. Unix.stackexchange.com/q/57957/70524strace grep .* file.txt |& head -n 1
иstrace grep '.*' file.txt |& head -n 1
. Также фактическиgrep
работает также с любым символом Unicode (например,echo -ne ⇏ | grep ⇏
выходами⇏
)bash
. Это означает, что сначалаbash
интерпретирует свои специальные символы и только после всех выполненных расширений передает параметры в порожденный процесс. ----- Например , эта команда в Bash:grep This.\*String file.txt
будет порождать/bin/grep
с этими параметрами 0:grep
1:This.*String
2:file.txt
. Обратите внимание, что Bash удалил обратную косую черту, и первоначально сбежавший*
был передан буквально.grep This.*String file.txt
правило, будут работать, потому что, скорее всего, не будет файла, соответствующего шаблонному выражению оболочкиThis.*String
. В таком случае по умолчанию Bash передаст аргумент буквально в том числе*
.*
Метасимвол в BRE 1 с, ERE 1 с и PCRE 1 совпадений с 0 или более вхождений ранее сгруппированных рисунка (если сгруппированы шаблон , предшествующие*
метасимвол), 0 или более вхождений предыдущего класса символов (если класс персонажа предшествующий*
метасимволу) или 0 или более вхождений предыдущего символа (если*
метасимвол не предшествует ни сгруппированному шаблону, ни классу символов );Это означает, что в
This*String
шаблоне, который является*
метасимволом, которому не предшествует ни сгруппированный шаблон, ни класс символов,*
метасимвол соответствует 0 или более вхождениям предыдущего символа (в данном случаеs
символа):Чтобы сопоставить 0 или более вхождений любого символа, вы хотите сопоставить 0 или более вхождений
.
метасимвола, который соответствует любому символу:*
Метасимвол в Бре и EREs всегда «жадный», т.е. он будет соответствовать самому длинному матчу:Это может быть не желаемое поведение; в случае , если это не так , вы можете включить
grep
«s PCRE двигатель ( с помощью-P
опции) и добавьте?
метасимвол, который когда ставится после*
и+
метасимволы имеет эффект изменения их алчность:1. Основные регулярные выражения, расширенные регулярные выражения и регулярные выражения, совместимые с Perl
источник
Одно из найденных здесь объяснений ссылка :
источник
*
имеет особое значение как в качестве символа для подстановки оболочки («подстановочный знак»), так и в качестве метасимвола регулярного выражения . Вы должны принять во внимание и то и другое, хотя, если вы заключите в кавычки свое регулярное выражение, вы можете помешать оболочке обработать его специально и убедиться, что оно передает его без изменений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как и в большинстве программ командной строки.) Например:Если вы используете
--color
флаг,grep
то выделите определенные части ваших строк, которые соответствуют вашему регулярному выражению, что очень полезно как для выяснения того, что делает регулярное выражение, так и для поиска того, что вы ищете, как только вы это сделаете. По умолчанию пользователи Ubuntu имеют псевдоним Bash, которыйgrep --color=auto
запускается - что достаточно для этой цели - при запускеgrep
из командной строки, поэтому вам, вероятно, даже не нужно проходить--color
вручную.1 Следовательно,
.*
в регулярном выражении означает, что*
означает в глобусе оболочки. Однако различие заключается в том,grep
что в любом месте автоматически печатаются строки, содержащие ваше совпадение , поэтому обычно нет необходимости иметь.*
начало или конец регулярного выражения.источник