bash命令替换冻结脚本(输出太长?)--如何应对

bash command substitution freezes script (output too long?)--how to cope

我有一个 bash 脚本,其中包含这样一行:

matches="`grep --no-filename $searchText $files`"

换句话说,我将 grep 的结果赋值给一个变量。

我最近发现那行代码似乎有一个漏洞:如果 grep 找到太多结果,它会烦人地简单地冻结执行。

首先,如果有人可以确认过多的输出(以及什么构成过多)是命令替换的已知危险,请为我提供可靠的 link。我进行了网络搜索,我能找到的最接近的参考文献是 this link:

"Do not set a variable to the contents of a long text file unless you have a very good reason for doing so."

这暗示有危险,但还很不充分。

其次,是否有应对此问题的已知最佳做法?

我真正想要的行为是在命令替换中过度输出 生成一个很好的人类可读的错误消息,然后是一个错误退出代码,这样我的脚本就会终止而不是冻结。 (注意:我总是 运行 我的脚本以 "set -e" 作为初始行之一)。有什么办法可以实现这种行为吗?

目前,我所知道的唯一解决方案是一种仅适用于我当前情况的 hack:我可以使用其 --max-count 选项限制 grep 的输出。

理想情况下,您根本不应该将未知长度的数据捕获到内存中;如果您在需要时阅读它,那么 grep 将等待内容准备好使用。

即:

while IFS= read -r match; do
  echo "Found a match: $match"
  # example: maybe we want to look at whether a match exists on the filesystem
  [[ -e $match ]] && { echo "Got what we needed!" >&2; break; }
done < <(grep --no-filename "$searchText" "${files[@]}")

这样,grep 仅在 read 准备好使用它时才写入一行(如果已经产生的输出多于可以产生的输出,则将阻塞而不需要继续读取输入存储在相对较小的管道缓冲区中)——所以你不需要的名字甚至不会首先生成,也不需要分配内存或以任何其他方式处理它们。