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