“grep -Rl”结果作为具有适当空间支持的 vi 参数

“grep -Rl”结果作为具有适当空间支持的 vi 参数

我正在尝试做类似的事情

vi `grep -Rl 'keyword'`

但我想支持文件名中的空格。

vi "`grep -Rl 'keyword'`"

不是做我需要的事情,它将 grep 输出转换为单个参数,其中包含 \n 。

我试过

vi "`grep -Rl 'keyword'`| xargs"

虽然看起来更好,但结果仍然是单个参数(现在用空格而不是 \n)。

有没有好的方法可以做到这一点? Bash 很好,因为符合 POSIX 标准而加分。

附言。

我知道 -R 选项不适用于所有 grep 实现,并且 bash 对于``.

答案1

使用find

find . -type f -exec grep -q 'pattern' {} \; -exec vi {} +

这将在当前目录中或当前目录下的每个常规文件中查找匹配的行pattern。对于这些找到的文件,vi将启动。

如果这些文件有几百个,vi就会调用批量文件。更改-exec vi {} +为对每个文件-exec vi {} \;调用一次。vi

我们使用它grep -q是因为我们实际上对 的输出根本不感兴趣grep,只对它的退出状态感兴趣。

这将允许任何有效的 Unix 文件名,并且完全符合 POSIX 标准(递归则grep不然)。

答案2

怎么样

grep -Rl 'pattern' | xargs -d '\n' vi

我不知道这个-d选项是如何 POSIXy 的。

如果您有 GNU 工具,最好允许任何文件名:

grep -Rlz 'pattern' | xargs -0 vi

答案3

在 bash 中,假设没有太多匹配的文件名$(getconf ARG_MAX),则另一种选择是循环遍历 globstar 下的扩展**并构建匹配的文件名数组:

shopt -s globstar
matching_files=()
for entry in **
do
  [ -f "$entry" ] || continue
  grep -q 'pattern' -- "$entry" && matching_files+=("$entry")
done
vi -- "${matching_files[@]}"

循环将查找当前目录及其下的非隐藏文件和目录;我们做的第一个测试是看看我们是否有一个纯文件。如果是这样,我们会grep对其运行安静/静音以获得所需的模式。如果文件包含该模式,我们将其文件名添加到matching_files数组中。最后,我们vi在数组中安全扩展的条目列表上运行。

如果您还想搜索隐藏文件和目录,请设置shopt -s dotglob.

相关内容