自从我学习了一些 bash 语法后,我就非常热衷于在日常生活中使用它。一个著名的命令是grep
. 如果需要 grep 某些东西但忽略多个文件,则下面的命令可能会起作用。
grep_ignore=("token_a", "token_b")
grep -rnw . -e "token2" | grep -v <(printf '%s\n' "${grep_ignore[@]}")
如何重现:
创建一些虚拟文件夹:命令运行
mkdir dummy & cd dummy
创建文件:
一种。
file_token_a.txt
:命令运行echo "token1 token2" > file_token_a.txt
;b.
file_token_b.txt
: 命令运行echo "token1 token3" > file_token_b.txt
C。
file_token_c.txt
: 命令运行echo "token2 token3" > file_token_c.txt
命令运行:
grep_ignore=("token_a", "token_b")
grep -rnw . -e "token2" | grep -v <(printf '%s\n' "${grep_ignore[@]}")
预期输出:
./file_token_c.txt:1:token2 token3
给定输出:
./file_token_c.txt:1:token2 token3
./file_token_a.txt:1:token1 token2
您的尝试有两个问题:
你的数组结构有一个错误的逗号,这使得第一个模式
token_a,
而不是token_a
<(printf '%s\n' "${grep_ignore[@]}")
正在grep -v
作为要搜索的文件传递给由进程替换的文件描述符字符串组成的模式,如/dev/fd/63
1,而不是作为模式列表 - 要从文件(或进程替换)中读取模式,您需要将其作为参数到-f
选项纠正这些:
然后
(
-F
据说将数组元素视为固定字符串而不是正则表达式)。或者,至少在 GNU grep 中,您可以使用
--exclude
(and--include
) 将匹配限制为特定文件子集,以避免完全避免第二个 grep。所以使用你上面的例子:但给定一个文件名模式数组(注意元素由空格而不是逗号分隔):
然后
其中数组参数扩展
${grep_ignore/#/--exclude=}
如下:或者,您可以使用大括号扩展而不是数组:
printf '%s\n' /dev/fd/{61..65} | grep -v <(printf '%s\n' "${grep_ignore[@]}")
例如,或运行您的命令set -x