find -exec grep 与反向 grep 串联,find 嵌套 grep

find -exec grep 与反向 grep 串联,find 嵌套 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;

答案1

你不需要find!...grep有一个选项:

-r,——递归 递归读取每个目录下的所有文件,仅当符号链接在命令行上时才遵循它们。请注意,如果没有给出文件操作数,grep 将搜索工作目录。这相当于 -d recurse 选项。

或者

-R, --dereference-recursive 递归读取每个目录下的所有文件。与 -r 不同,跟踪所有符号链接。

更多选择人grep


您可以从包含这三个文件的目录中运行以下命令。

仅排除单词BAD_word

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

或者排除包含该词的整行BAD_word

grep -wv "BAD_word" <(grep -rwn "GOOD_word" .)

答案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/**/*

也可以看看

相关内容