найти -exec grep последовательно с инвертированным grep, найти вложенный grep

У меня есть следующие три файла

**file_01.sh**  
GOOD_word  
bla bla BAD_word  
miao GOOD_word bau  
BAD_word
GOOD_word foo
**file_02.sh**  
GOOD_word yes  
GOOD_word bla bla BAD_word  
GOOD_word bla  
BAD_word  
**file_03.sh**  
just BAD_word  
and bla bla  

Я бы хотел получить следующий результат:

**“o_file.txt”:**  
./i_dir/file_01.sh:1:GOOD_word  
./i_dir/file_01.sh:3:miao GOOD_word bau  
./i_dir/file_01.sh:5:GOOD_word foo  
./i_dir/file_02.sh:1:GOOD_word yes  
./i_dir/file_02.sh:3:GOOD_word bla  

Это то, что я пробую пока , но не работает.

find ./dir -type f -exec grep -E -i -H "GOOD_word" {} \; | 
  grep -v “BAD_word” {} \; >> o_file.txt;
2
задан 11 December 2020 в 04:29

2 ответа

Вы близки - вам просто нужно добавить -n для номера строк и удалите второй {} , чтобы grep -v работал с выводом первого grep, а не с найденными файлами:

$ find ./i_dir -type f -exec grep -E -i -H -n "GOOD_word" {} \; | grep -v "BAD_word"
./i_dir/file_01.sh:1:GOOD_word
./i_dir/file_01.sh:3:miao GOOD_word bau
./i_dir/file_01.sh:5:GOOD_word foo
./i_dir/file_02.sh:1:GOOD_word yes
./i_dir/file_02.sh:3:GOOD_word bla

Я предполагаю что вам нужно -E , потому что ваше «настоящее» GOOD_word является расширенным регулярным выражением - если это не так, вы можете его опустить (и, возможно, также -i ).

В качестве альтернативы вы можете сделать что-то вроде этого, используя bash globstar для спуска каталога и awk для логики:

shopt -s globstar
awk '/GOOD_word/ && !/BAD_word/{print FILENAME,FNR,$0}' OFS=: ./i_dir/**/*

См. Также

3
ответ дан 3 January 2021 в 22:46

Вам не нужно найти ! ... grep имеет параметр для этого:

-r, --recursive Рекурсивно читать все файлы в каждом каталоге, переходя по символическим ссылкам, только если они находятся в командной строке. Обратите внимание: если файловый операнд не указан, grep ищет рабочий каталог. Это эквивалентно опции -d recurse.

или

-R, --dereference-recurse Рекурсивно считывать все файлы в каждом каталоге. Перейти по всем символическим ссылкам, В отличие от -r.

Дополнительные параметры находятся в man grep


Вы можете выполнить следующее из каталога, содержащего три файла.

Чтобы исключить только слово BAD_word :

sed 's/BAD_word//' <(grep -rwn "GOOD_word" .)

или исключить целые строки, содержащие слово BAD_word :

grep -wv "BAD_word" <(grep -rwn "GOOD_word" .)
4
ответ дан 3 January 2021 в 22:46

Другие вопросы по тегам:

Похожие вопросы: