排除文件的grep数组参数

我想从我的grep命令中排除一些文件,为此我使用参数:

 --exclude=excluded_file.ext 

为了更容易阅读,我想使用排除文件的bash数组:

 EXCLUDED_FILES=("excluded_file.ext") 

然后将$ {EXCLUDED_FILES}数组传递给grep ,如下所示:

 grep -Rni "my text" --exclude=${EXCLUDED_FILES} 

我如何可以将数组作为parameter passing给grep命令?

我想你正在寻找这个:

 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 

变量不会作为参数传递给程序; 是。 变量(尤其是数组)由shell扩展为一个或多个单词,每个单词作为单独的参数传递给程序。 在这种特殊情况下,– --exclude选项将单个文件名作为参数,所以您需要从数组中构建多个--exclude=foo参数。 一个选项:

 for f in "${EXCLUDED_FILES[@]}"; do opts+=( --exclude="$f" ) done grep -Rni "my text" "${opts[@]}" 

GNU grep还支持--exclude-from选项,该选项将文件名作为其参数,引用的文件包含要排除的模式,每个都在自己的行上。

如果您不担心带有嵌入换行符的文件名(很少担心),您可以使用如下的流程替换来即时创建这样一个文件:

 grep -Rni "my text" --exclude-from=<(printf '%s\n' "${EXCLUDED_FILES[@]}") 

另外:为避免与环境变量和特殊的shell变量冲突,最好不要使用全大写的shell变量名称。

GNU的人真的搞砸了,当他们给grep选项find文件。 接下来是什么 – sort输出或转换字符进行sort的选项或只打印结果的head / tail的选项? 用于查找文件的UNIX工具具有非常明显的名称find 。 UNIX工具grep也被恰当地命名为“ G在一个文件中匹配一个R egular E xpression并且记录结果”。

所以当grep从符合正则表达式的文件中打印字符串时, find找到的文件是非常不同的目的,您应该像UNIX设计者所期望的那样,为每个作业使用正确的工具:

 findsarg=() for f in "${EXCLUDED_FILES[@]}" do findsarg+=( '!' -name "$f" ) done find . -type f "${findsarg[@]}" -exec grep -Hni "my text" {} + 

感谢@gniourf_gniourf获取处理包含元字符和空格的文件名的语法。

正如其他地方提到的那样 – 不要按照惯例为非导出的变量使用所有的大写字母名称,并且避免与导出的/标准的名字相冲突。

您不能从字面上将数组作为参数传递给任何命令。 所有参数都是字符串。

但是,您可以将数组转换为包含所有数组元素的字符串(用分隔符分隔)(默认情况下为一个空格字符)。 语法是

 grep -Rni "my text" --exclude="${EXCLUDED_FILES[*]}" 

然而,我应该指出,GNU grep排除参数不适用于这种方式。 它的值是作为一个单一的 glob来过滤结果。 这不同于--exclude-from参数将文件的每一行视为单独的glob的行为。 如果你想在命令行中指定多个排除球体,那么你需要分别为每个--exclude提供一个--exclude参数。