【问题标题】:An "and" operator for an "if" statement in BashBash 中“if”语句的“and”运算符
【发布时间】:2012-11-04 16:48:42
【问题描述】:

我正在尝试创建一个简单的 Bash 脚本来检查网站是否已关闭,并且由于某种原因“and”运算符不起作用:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="an@email.com"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"

if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi

“-a”运算符也不起作用:

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

能否请您告知何时使用:

  • 单方括号和双方括号
  • 括号

?

【问题讨论】:

  • 您能否更准确地说明什么“不起作用”?您是否有特定的错误消息,或者根本没有提供预期的输出?
  • 我实际上收到了“预期的一元运算符”,所以看起来引用有帮助
  • -a 具有重复性。当与 Bourne shell 风格的 test 命令(又名 [)一起使用时,它的意思是 and。当用作 条件表达式 时,它正在测试文件是否存在。是的,这令人困惑,最好避免。

标签: bash if-statement


【解决方案1】:

试试这个:

if [ "${STATUS}" -ne 100 -a "${STRING}" = "${VALUE}" ]

if [ "${STATUS}" -ne 100 ] && [ "${STRING}" = "${VALUE}" ]

【讨论】:

  • 加上最干净的例子
【解决方案2】:

引用:

“-a”运算符也不起作用:

如果 [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

更详细的解释:[] 不是 Bash 保留字。 if 关键字引入了要由作业评估的条件(如果作业的返回值为 0,则条件为真,否则为假)。

对于简单的测试,有test 程序 (man test)。

由于某些行如if test -f filename; then foo bar; fi 等令人讨厌,在大多数系统上,您会发现一个名为[ 的程序实际上只是test 程序的符号链接。当test 被称为[ 时,您必须添加] 作为最后一个位置参数。

所以if test -f filenameif [ -f filename ] 基本相同(就产生的进程而言)。在这两种情况下,test 程序都会启动,并且两个进程的行为应该相同。

这是你的错误:if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]] 将解析为 if + 一些工作,工作是除了 if 本身之外的所有内容。这项工作只是一个简单的命令(Bash 表示会导致单个进程的东西),这意味着第一个单词 ([) 是命令,其余的是它的位置参数。 在第一个]之后还有剩余的参数

同样不是,[[ 确实是一个 Bash 关键字,但在这种情况下它只被解析为一个普通的命令参数,因为它不在命令的前面。

【讨论】:

    【解决方案3】:

    除非${STATUS} 为空,否则您所拥有的应该可以工作。这样做可能会更好:

    if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then
    

    if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then
    

    很难说,因为你没有向我们确切地展示你的脚本出了什么问题。

    个人意见:永远不要使用[[。它抑制重要的错误消息,并且不能移植到不同的 shell。

    【讨论】:

    • 如果STATUS 为空,来自@HTF 的代码将在-ne: unary operator expected 上失败。在你的情况下,它会在integer expression expected 上失败,不是吗?
    • 我明白这一点。但是您强调了$STATUS 可能为空的问题并提出了解决方案(引用它)。你的解决方案仍然失败,STATUS 是空的,这就是我的意思。
    • @jvivenot 你说得有道理。 (我对您的评论的回复是在您编辑评论之前做出的,当时您的评论只是“代码......会失败”。一个简单的解决方案是使用${STATUS:-0"。将编辑。
    • 进一步,考虑由 [[ 在a="this is not an integer"; test "$a" -ge 0; [[ $a -ge 0 ]]; IMO 中生成的(缺少)错误消息,该错误消息很有用,并且 [[ 错误地抑制了它。此外,[[ 返回 0,而 test 返回 1。IMO,这使得 [[ 无法使用。
    • @Mercury 是的,我对此持强烈的看法。缺少来自[[ 的错误消息是有问题的。 [[ 解决了因对test 工作原理的误解而引起的问题。 IMO,解决这些问题的更好方法是了解如何使用test
    【解决方案4】:

    试试这个:

    if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
    

    【讨论】:

    • 为我工作。我认为可能有不止一种方法,但我现在对此感到满意。
    • 看起来在某些情况下效果更好。 && 运算符看起来不适用于 shell 替换和两个 &&。我建议先试试这个选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 2021-11-14
    • 2011-01-13
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多