将grep命令的输出存储在数组中

74

我需要在目录中搜索一个模式,并将包含该模式的文件名保存在一个数组中。

搜索模式:

grep -HR "pattern" . | cut -d: -f1

这将打印出所有包含“pattern”的文件名。

如果我尝试:

targets=$(grep  -HR "pattern" . | cut -d: -f1)
length=${#targets[@]}
for ((i = 0; i != length; i++)); do
   echo "target $i: '${targets[i]}'"
done

这会仅打印一个元素,其中包含一个带有所有文件名的字符串。

output: target 0: 'file0 file1 .. fileN'

但是我需要:

 output: target 0: 'file0'
 output: target 1: 'file1'
 .....
 output: target N: 'fileN'

我该如何在不进行繁琐的字符串分割操作的情况下实现这个结果呢?


另一个答案是通过运行任何命令来构建数组的通用方法,而这个问题是特定于 grep --null -HR 以产生带有 NUL 字节的输出。 - anubhava
1个回答

113
旧答案(写于2014年)假设输出文件名不包含特殊字符,如空格或通配符。这里有一种安全的方法将这些特殊文件名读入数组中:(适用于旧版本的bash)
while IFS= read -rd ''; do
   targets+=("$REPLY")
done < <(grep --null -HRl "pattern" .)

# check content of array
declare -p targets

在BASH 4+中,你可以使用readarray代替循环:
readarray -d '' -t targets < <(grep --null -HRl "pattern" .)

旧答案:

你可以使用:

targets=($(grep -HRl "pattern" .))

注意在BASH中使用(...)来创建数组。
另外,你可以使用grep -l来仅获取grep输出中的文件名(如我的命令所示)。

太棒了!我已经看了一下“-l”选项,顺便说一句,非常好。你能解释一下为什么加两个括号就可以工作吗? - Luca Davanzo
2
这是在BASH中创建数组的语法。如果您删除外部的 (..),那么您只是将 grep 的输出分配给一个简单的shell变量,它不会被视为数组。 - anubhava
2
如果有这种可能性,那么请使用grep --nullIFS=来创建数组。 - anubhava
这个能在类似于一些BSD和Solaris的Posix-ly操作系统上工作吗?我没有看到-H-R - jww
在旧版的 grep 中可能没有 -R 选项。此时可以使用在这些系统上使用 find -exec grep 的替代方法。 - anubhava
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接