我想从grep
命令中排除一些文件,为此我使用参数:
--exclude=excluded_file.ext
为了更容易阅读,我想使用带有排除文件的bash数组:
EXCLUDED_FILES=("excluded_file.ext")
然后将$ {EXCLUDED_FILES}数组传递给grep
,如:
grep -Rni "my text" --exclude=${EXCLUDED_FILES}
如何将数组作为参数传递给grep
命令?
答案 0 :(得分:9)
变量不作为参数传递给程序; 值是。变量(尤其是数组)由shell扩展为一个或多个单词,每个单词作为单独的参数传递给程序。在这种特定情况下,--exclude
选项将单个文件名作为其参数,因此您需要从数组中构建多个--exclude=foo
参数。一种选择:
for f in "${EXCLUDED_FILES[@]}"; do
opts+=( --exclude="$f" )
done
grep -Rni "my text" "${opts[@]}"
答案 1 :(得分:6)
我想你正在寻找这个:
grep -Rni "${excluded_files[@]/#/--exclude=}" "my text"
参数展开"${excluded_files[@]/#/--exclude=}"
将扩展为数组excluded_files
的扩展,每个字段都以--exclude=
为前缀。看:
$ excluded_files=( '*.txt' '*.stuff' )
$ printf '%s\n' "${excluded_files[@]/#/--exclude=}"
--exclude=*.txt
--exclude=*.stuff
答案 2 :(得分:2)
GNU grep
还支持--exclude-from
选项,该选项将 filename 作为其参数,引用的文件包含要排除的模式,每个模式都在其自己的行上。
如果您不担心带有嵌入换行符的文件名(很少有人担心),您可以使用以下流程替换来动态创建这样的文件:
grep -Rni "my text" --exclude-from=<(printf '%s\n' "${EXCLUDED_FILES[@]}")
顺便说一下:最好不要使用全大写的shell变量名来avoid conflicts with environment variables and special shell variables。
答案 3 :(得分:2)
当他们为grep
文件提供find
选项时,GNU的人真的搞砸了。接下来的内容 - sort
输出的选项或tr
安全字符或仅打印结果的head
/ tail
?用于查找文件的UNIX工具具有非常简单明了的名称find
。 UNIX工具grep
也恰当地命名为&#34; G 与一个文件中的 R egular E xpression进行全局匹配 P 判断结果&#34;。
所以find
找到文件,而grep
从匹配正则表达式的文件中打印字符串 - 2个非常不同的目的,你应该像UNIX设计师那样为每个作业使用正确的工具:
findsarg=()
for f in "${EXCLUDED_FILES[@]}"
do
findsarg+=( '!' -name "$f" )
done
find . -type f "${findsarg[@]}" -exec grep -Hni "my text" {} +
感谢@gniourf_gniourf帮助获取处理包含globbing元字符和空格的文件名的语法。
正如其他地方所述 - 不按惯例使用非导出变量的所有大写名称,以避免与导出/标准名称发生冲突。
答案 4 :(得分:1)
您不能将数组作为参数传递给任何命令。所有参数都是字符串。
但是,您可以将数组转换为包含所有数组元素的字符串,并以分隔符(默认情况下为一个空格字符)分隔。语法是
grep -Rni "my text" --exclude="${EXCLUDED_FILES[*]}"
但是,我应该指出,GNU --exclude
的{{1}}参数不起作用。它的值被视为单个 glob,用于过滤结果。这不同于grep
参数将文件的每一行视为单独的glob的行为。如果要在命令行中指定多个排除球,那么您需要为每个参数分别提供--exclude-from
参数。