Использование знака звездочки в grep

88

Я пытаюсь найти подстроку «abc» в конкретном файле в linux / bash

Итак, я делаю:

grep '*abc*' myFile

Он ничего не возвращает.

Но если я это сделаю:

grep 'abc' myFile

Он правильно возвращает совпадения.

Теперь для меня это не проблема. Но что, если я хочу найти более сложную строку, например

*abc * def *

Как мне это сделать с помощью grep?

Саоби
источник
3
Сам grep не поддерживает подстановочные знаки на большинстве платформ. Для использования подстановочных знаков необходимо использовать egrep. Оболочки имеют другой синтаксис. «*» в оболочке - это <любая строка>. В egrep это оператор, который говорит «0 многим из предыдущих объектов». В grep это обычный символ.
PanCrit 01
@PanCrit: *означает то же самое в grep и egrep: это квантификатор, означающий ноль или более предшествующих атомов. Это совершенно другая концепция, чем подстановочные знаки, используемые оболочкой.
Алан Мур

Ответы:

123

Звездочка - это просто оператор повторения , но вам нужно указать ему, что вы повторяете. /*abc*/соответствует строке, содержащей ab и ноль или более c (потому что вторая * находится на c; первая бессмысленна, потому что ей нечего повторять). Если вы хотите сопоставить что-либо, вам нужно сказать .*- точка означает любой символ (в рамках определенных правил ). Если вы хотите просто сопоставить abc, вы можете просто сказать grep 'abc' myFile. Для более сложного соответствия вам необходимо использовать .*- grep 'abc.*def' myFileбудет соответствовать строке, содержащей abc, за которой следует def с чем-то, необязательно между ними.

Обновление на основе комментария:

*в регулярном выражении не совсем то же самое, что * в консоли. В консоли * является частью конструкции glob и просто действует как подстановочный знак (например ls *.log, перечислит все файлы, которые заканчиваются на .log). Однако в регулярных выражениях * является модификатором, что означает, что он применяется только к предшествующему ему символу или группе. Если вы хотите, чтобы * в регулярных выражениях действовал как подстановочный знак, вам необходимо использовать, .*как упоминалось ранее: точка является подстановочным знаком, а звездочка при изменении точки означает поиск одной или нескольких точек; т.е. найти одного или нескольких персонажей.

Даниэль Вандерслуис
источник
1
Я думаю, что вопросник смущен различием между подстановочными знаками оболочки и регулярными выражениями. Я также подозреваю, что более сложным выражением было бы: grep 'abc. * Def' (присутствует хотя бы один пробел - возможно, два, как я писал).
Джонатан Леффлер,
1
На самом деле, похоже, спрашивающий не понимает, что «abc» - это не то же самое, что «^ abc $» :-D
Масса
1
Да, я запутался между glob и полными регулярными выражениями. Я использую * без точки, чтобы обозначить соответствие чему-либо в оболочке.
Saobi 01
1
grep *означает «0 или больше», а grep по умолчанию является жадным. Обратите внимание , что в Grep основных регулярных выражений метасимволы ?, +, {, |, (, и )теряют особый смысл. Более подробная информация: grep regexps
KrisWebDev
25

Точка означает совпадение с любым символом, т.е. .*означает ноль или более вхождений любого символа. Вы, вероятно, хотите использовать, .*а не просто *.

smcameron
источник
Точка - это метасимвол, который принимает любой символ, кроме новых строк .
Абхишек Камаль
12

«Знак зодиака» имеет значение, только если перед ним что-то есть. Если инструмента нет (в данном случае grep), это может просто обработать его как ошибку. Например:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz
Джонатан Леффлер
источник
5
* Не бессмысленно; это просто не имеет своего обычного значения (повторения), но означает «Я звезда». Он будет соответствовать строке, содержащей звезду, за которой следуют x, y и z.
Джонатан Леффлер,
2
@Jonathan Это зависит от инструмента.
7

Используйте команду grep -P - которая включает поддержку регулярных выражений в стиле Perl.

grep -P "abc.*def" myfile
Артем Русаковский
источник
6

Выражение, которое вы пробовали, как и те, которые работают, например, в командной строке оболочки в Linux, называется « glob ». Выражения Glob не являются полноценными регулярными выражениями , которые grep использует для указания строк, которые нужно искать. Вот (старый, небольшой) пост о различиях. Выражения glob (например, "ls *") интерпретируются самой оболочкой.

Переводить из глобусов в RE можно, но обычно это нужно делать в уме.

размотать
источник
1
Это только глобус, если он разбирается оболочкой. Поскольку он сохраняет строку поиска внутри одинарных кавычек, оболочка оставляет строку в покое и передает ее в неизменном виде в argv в grep.
Conspicuous Compiler
4

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

Эндрю Билс
источник
2
fgrepтеперь устарел, grep -fследует использовать вместо него.
Прометей
1
Это "grep -F". Старый добрый fgrep может быть "устаревшим", но они не собираются убирать его, пока я жив.
Эндрю Билс
1

Это может быть ответ, который вы ищете:

grep abc MyFile | grep def

Единственное, что ... он будет выводить строки, в которых "def" стоит перед OR после "abc"

Чарльз Дюк
источник
1

Это сработало для меня:

grep ". * $ {expr}" - в двойных кавычках, которым предшествует точка. Где «expr» - это любая строка, которая вам нужна в конце строки.

Стандартный unix grep без дополнительных ключей.

доступ разрешен
источник
0

'*' работает как модификатор для предыдущего элемента. Таким образом, "abc * def" ищет "ab", за которым следует 0 или более "c", за которыми следует "def".

Вам, вероятно, понадобится «abc. * Def», который ищет «abc», за которым следует любое количество символов, за которым следует «def».

Заметный компилятор
источник