【问题标题】:Checking the success of a command in a bash `if [ .. ]` statement在 bash `if [ .. ]` 语句中检查命令是否成功
【发布时间】:2016-07-22 03:20:35
【问题描述】:

我正在尝试自动化我们的应用程序备份。该过程的一部分是在if 语句中检查egrep 的退出状态:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   [ egrep -i -q "error|warning|fatal|missing|critical" "$File" ]
then 
  echo "testing"
fi

我希望它输出testing,因为文件存在并且egrep 返回成功,但我却得到了一个错误:

-bash: [: too many arguments

我尝试了各种语法 - 额外的括号、引号等,但错误仍然存​​在。

请帮助我了解我哪里出错了。

【问题讨论】:

  • @DavidGrayson:这并不意味着它“有效”。
  • egrep 不应用括号括起来。
  • David :在系统中存在的文件上使用 -f 尝试它,您将得到与 Abhinandan 相同的错误。
  • 感谢大家的回复。 @kichik - 删除 egrep 周围的括号有效.. 非常感谢:)

标签: bash if-statement


【解决方案1】:

您犯了一个常见错误,即假设[if 语句语法的一部分。它不是; if 的语法很简单

if command; then
    : # ... things which should happen if command's result code was 0
else
    : # ... things which should happen otherwise
fi

我们使用的常见commands 之一是[,它是命令test 的别名。这是一个比较字符串、数字和文件的简单命令。它接受相当狭窄的参数组合,如果您不传递预期的参数,往往会产生令人困惑和误导的错误消息。 (或者更确切地说,一旦你习惯了错误消息,它们就足够了,而且很有帮助,但如果你不习惯,它们很容易被误解。)

这里,你要检查命令egrep的结果:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   egrep -i -q "error|warning|fatal|missing|critical" "$File"
then
    echo "testing"
fi

一般情况下,command 可以是管道或命令列表;然后,最终命令的退出代码是if 将检查的状态,类似于脚本中的最后一个命令如何决定脚本的退出状态。

这些复合命令可以任意复杂,比如

if read thing
    case $thing in
      '' | 'quit') false;;
      *) true;;
    esac
then ...

但在实践中,您很少会在 if 语句中看到多个命令(尽管这并非闻所未闻;您与 || 的复合语句就是一个很好的例子!)

只是为了说明这一点,

if [ egrep foo bar ]

在参数 egrep foo bar 上运行 [ aka test。但是没有选项的[ 只接受一个参数,然后检查该参数是否为空字符串。 (egrep 显然不是一个空字符串。在这里引用是可选的,但也许会更容易看到:

if [ "egrep" ]; then
    echo "yes, 'egrep' is not equal to ''"
fi

这显然是孤立的,但希望可以作为一个说明性的例子。)

test 作为一般厨房水槽的历史原因,作者不想成为if 语法的一部分,这是原始 Bourne shell 不太吸引人的设计之一。 Bash 和 zsh 提供了不太笨重的替代方案(如 bash 中的 [[ 双括号),当然,POSIX test 比贝尔实验室的原始创建要好得多。

【讨论】:

  • 这是this earlier answer of mine 对一个类似问题的改编。
  • Nit pick:if 语法实际上是 if list of commands; then,最后一个命令确定状态。 command 可能是一个管道。
  • @Jens 谢谢,非常精明!已更新。
  • 谁能解释一下为什么在其他语言中 0 被认为是假的(而其他数字是真的),而这里的 0 被认为是真值?谢谢
  • @silvanasono 快速谷歌搜索让我知道Why 0 is true but false is 1 in the shell?
【解决方案2】:

这可行:将您的 egrep 放入“$()”,删除 -q 并进行字符串比较:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   [ "$(egrep -i 'error|warning|fatal|missing|critical' $File)" != "" ];
then

   echo "testing";

fi

【讨论】:

  • 注意:如果 $File 包含空格将不起作用... bash 让我头疼!如何将双引号放入双引号!
  • 投反对票:请不要扩散useless backticks的反模式
猜你喜欢
  • 2015-02-23
  • 2017-02-09
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多