Отрицательное сопоставление с использованием grep (сопоставление строк, не содержащих foo)

993

Я пытался выработать синтаксис этой команды:

grep ! error_log | find /home/foo/public_html/ -mmin -60

ИЛИ:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

Мне нужно увидеть все файлы, которые были изменены, кроме названных error_log.

Я читал об этом здесь , но нашел только один notшаблон -regex.

jerrygarciuh
источник
13
[^ error_log] никогда бы не сработал, [] - это классы char, регулярные выражения вообще не годятся для отрицательных шаблонов (если механизм не реализует отрицательные запросы).
Яап

Ответы:

1759

grep -v твой друг:

grep --help | grep invert  

-v, --invert-match выбрать несовпадающие строки

Также проверьте связанные -L(дополнение -l).

-L, --files-without-match only печатать имена файлов, не содержащие совпадений

Моти
источник
125
Стоит отметить, что для нескольких (отрицательных) матчей -eможет быть использована опция:grep -v -e 'negphrase1' -e 'negphrase2'
Бабкен Варданян
31
Аналогично комментарию от @ Babken-Vardanyan Также - возможность использовать каналы для объединения нескольких матчей, напримерgrep -v 'negphrase1|negphrase2|negphrase3'
Николас Адамс
13
Последний комментарий НЕ является тем же самым, поскольку он будет искать вещи, которые не соответствуют ни тому, ни другому. т.е. если он соответствует одному, но не другому, он все еще печатается. Попробуйте оба варианта с не похожими строками
Эван Ланглуа
7
@EvanLanglois - заставляет grep интерпретировать шаблон как расширенное регулярное выражение с использованием -Eworks, т.е. grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini
1
@ OlleHärstedt, я думаю , что я неправильно понял ваш сценарий в моем предыдущем комментарии, нижеследующее может быть то , что вы ищете grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( почему первый Grep? , Всегда есть способ :))
Моти
139

Вы также можете использовать awkдля этих целей, так как это позволяет вам выполнять более сложные проверки более ясным способом:

Линии, не содержащие foo:

awk '!/foo/'

Строки, не содержащие fooни bar:

awk '!/foo/ && !/bar/'

Строки , не содержащие ни fooни , barкоторые содержат либо foo2или bar2:

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

И так далее.

Федорки "ТАК прекратить вредить"
источник
2
Это на самом деле довольно круто. Вам даже не нужно изучать полный язык awk, чтобы сгруппировать регулярные выражения с логическими операторами. Спасибо за этот ответ!
Питер Т.
1
Именно то, что я искал, большое спасибо.
mmrs151
14

В вашем случае вы, вероятно, не хотите использовать grep, но вместо этого добавляете отрицательное предложение в команду find, например

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

Если вы хотите включить в имя символы подстановки, вам нужно их экранировать, например, чтобы исключить файлы с суффиксом .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
Папа смурф
источник