Как grep, исключая некоторые шаблоны?

Я бы хотел найти строки в файлах с появлением некоторого шаблона и отсутствием какого-либо другого шаблона. Например, мне нужно найти все файлы/строки, включая loom, кроме тех, у которых gloom. Итак, я могу найти loom с командой:

grep -n 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Теперь я хочу выполнить поиск loom исключая gloom. Однако обе следующие команды не выполнялись:

grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Что я должен сделать для достижения своей цели?

EDIT 1: Я имею в виду, что loom и gloom - это последовательности символов (не обязательно слова). Поэтому мне нужно, например, bloomberg в выводе команды и не нуждаться в ungloomy.

EDIT 2: Есть пример моих ожиданий. Обе следующие строки находятся в командном выводе:

Я столкнулся с иконами, которые маячили сквозь завесу благовоний.

Арти засыпает в мрачный день.

Обе следующие строки не выводятся командой:

Его мраморный ужас ужасный - великие хитросплетения o cloods.

В юго-западном круге зала хип-пейнтита

Ответ 1

Как просто связать greps?

grep -n 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp) | grep -v 'gloom'

Ответ 2

Другое решение без привязки grep:

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Между скобками вы исключаете символ g перед любым вхождением loom, если только loom не является первым символом строки.

Ответ 3

Немного старый, но хорошо...

Самое популярное решение от @houbysoft не будет работать, так как это исключает любую строку с "мрак" в ней, даже если у нее есть "ткацкий станок". Согласно ожиданиям OP, мы должны включать строки с "ткацким станком", даже если они также имеют "мрак" в них. Эта строка должна быть в выводе "Arty - это ураган в мрачный день", но это будет исключено прикованным grep вроде

grep -n 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp) | grep -v 'gloom'

Вместо этого egrep regex пример Bentoy13 работает лучше

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

поскольку он будет включать в себя любую строку с "ткацкой станцией" в ней, независимо от того, имеет ли она "мрак" . С другой стороны, если он только уныл, он не включит его, а именно то, что хочет OP.

Ответ 4

Просто используйте awk, это намного проще grep, позволяя вам четко выразить сложные условия.

Если вы хотите пропустить строки, содержащие как loom, так и gloom:

awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

или если вы хотите их распечатать:

awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

и если реальность - это просто строки, где loom появляется как само слово:

awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Ответ 5

-v - это флаг "перевернутого соответствия", поэтому трубопровод - это очень хороший способ:

grep "loom" ~/projects/**/trunk/src/**/*[email protected](h|cpp)| grep -v "gloom"

Ответ 6

/* Возможно, вы выглядите примерно так?

grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*[email protected](h|cpp)`

BACKQUOTES используются как скобки для команд, поэтому в этом случае с включенным -l код в BACKQUOTES вернет вам имена файлов, а затем -vn сделает все, что вам нужно: иметь имена файлов, простыни, а также фактические строки.

ОБНОВЛЕНИЕ Или с помощью xargs

grep -l "loom" ~/projects/**/trunk/src/**/*[email protected](h|cpp) | xargs grep -vn "gloom"

Надеюсь, что это поможет. */

Пожалуйста, проигнорируйте то, что я написал выше, это мусор.

grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom"

               #this part gets the filenames with "loom"
#this part gets the lines with "loom"
                                          #this part gets the linenumber,
                                          #filename and actual line

Ответ 7

Вы можете использовать grep -P (perl regex) поддерживаемый negative lookbehind:

grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Я добавил \b для границ слов.

Ответ 8

grep -n 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp) | grep -v 'gloom'

Ответ 9

Вопрос: найдите "ткацкий станок", исключая "мрак".
Ответ:

grep -w 'loom' ~/projects/**/trunk/src/**/*[email protected](h|cpp)

Ответ 10

Просто используйте! grep -v несколько раз.

Содержание файла

[[email protected]]# cat file
1
2
3
4
5

Исключить строку или совпадение

[[email protected]]# cat file |grep -v 3
1
2
4
5

Исключить строку или сопоставить несколько

[[email protected]]# cat file |grep -v 3 |grep -v 5
1
2
4