Bash中“ if”语句的“ and”运算符


168

我正在尝试创建一个简单的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" ]]

您还可以建议何时使用:

  • 单方和双方括号
  • 插入语


3
您能更精确地了解什么“无效”吗?您是否有特定的错误消息,或者仅仅是没有提供预期的输出?
朱利安·维维诺

我实际上收到的是“期望的一元运算符”,因此似乎在引用帮助
HTF 2012年

-a有双重性。与Bourne shell样式test命令aka一起使用时[,它表示and。当用作条件表达式时,它正在测试以查看文件是否存在。是的,这令人困惑,最好避免。
cdarke

Answers:


254

您拥有的东西应该可以工作,除非${STATUS}是空的。这样做可能会更好:

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

要么

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

很难说,因为您没有向我们确切显示脚本出了什么问题。

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


2
如果STATUS为空,则@HTF中的代码将在上失败-ne: unary operator expected。在您的情况下,它会失败integer expression expected,不是吗?
朱利安·维维诺

1
我明白那个。但是,您要突出显示$STATUS可能为空的问题并提出解决方案(引用)。您的解决方案仍然失败,显示为空STATUS,这就是我的意思。
朱利安·维维诺

1
@jvivenot你有意思。(写了我对您的评论的回应,您编辑您的评论,当您的评论仅仅是读取之前“的代码......就失败了”一个简单的解决方案是使用。${STATUS:-0"将编辑。
威廉Pursell

抱歉,您的修改仍然无法进行。例如:即使STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo foo不输出foo,也不会输出(空值不同于13)。您首先提出的建议${STATUS:-0}看起来要好得多。
朱利安·维维诺

@jvivenot如果${STATUS:-0}会失败STATUS=foo,但! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foo可以使用。IMO,最好避免-eq使用!=
威廉·珀塞尔

28

试试这个:

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

为我工作。我认为可能有不止一种方法,但是我对此感到满意。
库舒尔·阿肖克

26

试试这个:

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

要么

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

加上最干净的例子
Pawel Cioch

12

引用:

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

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

对于更详尽的解释:[并且]不是Bash保留的单词。该if关键字引入有条件通过工作来评估(条件为真,当作业的返回值是0或否则为false)。

对于微不足道的测试,有test程序(man test)。

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

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

这是您的错误:if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]将解析为if+一些工作,该工作是除if自身之外的所有东西。这项工作只是一个简单的命令(Bash表示要在单个过程中完成的事情),这意味着第一个单词([)是命令,其余部分是位置参数。在第一个之后还有其他参数]

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.