![find -exec grep 与反向 grep 串联,find 嵌套 grep](https://linux22.com/image/1178662/find%20-exec%20grep%20%E4%B8%8E%E5%8F%8D%E5%90%91%20grep%20%E4%B8%B2%E8%81%94%EF%BC%8Cfind%20%E5%B5%8C%E5%A5%97%20grep.png)
我有以下三个文件
**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/**/*
也可以看看