在工作脚本中将stdout重定向到/ dev / null的grep是什么意思?

时间:2018-07-04 14:07:07

标签: bash grep

我有一个bash脚本,是作为bash作业提交的。它创建一些文件,执行一些计算,将输出文件移到其他地方并清理。为了移动输出文件,它包含以下几行:

set -e
mv $tmp/stdout.txt $current/tmp.stdout.txt
grep Report $current/tmp.stdout.txt >/dev/null 2>&1
mv $current/tmp.stdout.txt $current/stdout.txt
set +e

如果计算成功,则输出文件stdout.txt包含几行以Report开头的行;但是没有的话就没有。进一步的处理将检查$current/stdout.txt文件是否存在(否则重新提交作业)。

第一个mv使用临时名称将输出文件从临时目录移动到最终目录;第二个mv将输出文件重命名为其最终名称。但是,grep之间的目的是什么?如果输出文件包含带有Report的行,它们将被重定向到\dev\null,并且什么也没有发生。如果输出文件不包含带有Report的行,则它不会输出任何内容,既不会输出到重定向的stdout,也不会输出到重定向的stderr。因此,我的印象是该行不执行任何操作,因此我应将mv + grep + mv替换为一个mv。我在这里忽略了哪些功能?

3 个答案:

答案 0 :(得分:6)

set -e在这里很重要。

  • grep将其退出状态设置为0,表示已成功处理输入文件并找到了任何结果,否则返回非零值。
  • set -e告诉外壳程序退出,如果任何已检查的命令具有非零退出状态。 (它有很多陷阱和警告,通常不应该使用;请参阅BashFAQ #105。)

因此-除非将此代码嵌入触发set -e无效的几种情况之一的上下文中-如果mv,脚本将在第二个grep之前终止没有匹配项。


编写脚本这一部分的更好方法是:

mv "$tmp/stdout.txt" "$current/tmp.stdout.txt" || exit
grep -q Report "$current/tmp.stdout.txt" || exit
mv "$current/tmp.stdout.txt" "$current/stdout.txt" || exit
  • grep -qgrep >/dev/null更有效率,因为它可以在看到匹配项时立即退出,否则grep需要一直读取到输入文件的末尾。 (2>/dev/null通常是不好的做法,因为它隐藏了您需要了解的有关调试不当行为的错误;因此,请在此处将其删除。)
  • 报价使带有空格或glob字符的变量安全,否则就不会。
  • 出于BashFAQ #105中给出的原因,将|| exit放在要致命的错误的单个命令上比依赖set -e可靠得多(请跳过以下练习的寓言,如果急忙,或查看https://www.in-ulm.de/~mascheck/various/set-e/以了解已知set -e的行为在不同的shell和/或shell版本之间有所不同的情况的列表。

答案 1 :(得分:2)

如果未找到匹配项,Grep将返回错误代码。

set -e表示错误将停止脚本。

grep上还有其他选项,这意味着它没有输出,而不是进行所有捕获。

答案 2 :(得分:1)

set -ebash配置为在遇到第一个错误时中止。如果grep失败(不查找任何内容),则bash将在grep之后终止。

大多数grep版本都知道-q选项,该选项使它们安静(抑制所有输出),因此不再需要重定向。另外,依赖set -e的代码也不容易维护。适当的grep ... || exit 1会更明确。