Оператор «и» для оператора «if» в Bash

168

Я пытаюсь создать простой скрипт Bash, чтобы проверить, не работает ли веб-сайт, и по какой-то причине оператор «и» не работает:

#!/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" ]]

Не могли бы вы также посоветовать, когда использовать:

  • одинарные и двойные квадратные скобки
  • круглая скобка

?

HTF
источник
3
Не могли бы вы быть более точным относительно того, что "не работает"? У вас есть конкретное сообщение об ошибке, или он просто не обеспечивает ожидаемый результат?
Жюльен Вивнот
Я на самом деле получал "ожидался унарный оператор", поэтому похоже, что цитирование помогает
HTF
-aимеет двуличность При использовании с командой стиля оболочки Bourne test, иначе [это означает and. При использовании в качестве условного выражения он проверяет, существует ли файл. Да, это сбивает с толку, лучше избегать.
cdarke
Проверьте это: theunixshell.blogspot.com/2013/05/…
Виджай,

Ответы:

254

То, что у вас есть, должно работать, если ${STATUS}не пусто. Вероятно, было бы лучше сделать:

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

или

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

Трудно сказать, так как вы не показали нам точно, что не так с вашим сценарием.

Личное мнение: никогда не использовать [[. Он подавляет важные сообщения об ошибках и не переносится на разные оболочки.

Уильям Перселл
источник
2
Если STATUSон пуст, код из @HTF не был бы включен -ne: unary operator expected. В вашем случае это не удастся integer expression expected, не так ли?
Жюльен Вивнот
1
Я это понимаю. Но вы выделяете проблему, которая $STATUSможет быть пустой, и предлагаете решение (цитируя ее). Ваше решение все еще терпит неудачу с пустым STATUS, это все, что я имел в виду.
Жюльен Вивнот
1
@jvivenot У вас есть точка зрения. (Мой ответ на ваш комментарий был сделан до того, как вы отредактировали свой комментарий, когда в вашем комментарии просто читалось: «код ... был бы сбой». Простое решение - использовать ${STATUS:-0". Будет редактировать.
Уильям Перселл,
Извините, ваша правка все еще не работает. Например: 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работает. ИМО, лучше избегать -eqи использовать !=, хотя.
Уильям Перселл
28

Попробуй это:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
BrenanK
источник
работал на меня. Я думаю, что может быть несколько способов, но я доволен этим на данный момент.
Кушал Ашок
27

Попробуй это:

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

или

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram
источник
плюс для самого чистого примера
Pawel Cioch
12

Quote:

Оператор "-a" также не работает:

if [$ 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 filenameв основном то же самое (с точки зрения порожденных процессов) как if [ -f filename ]. В обоих случаях testпрограмма будет запущена, и оба процесса должны вести себя одинаково.

Вот ваша ошибка: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]проанализирую if+ некоторую работу, работа - это все, кроме самой ifсебя. Задание является простой командой (Bash говорит о чем-то, что приводит к одному процессу), что означает, что первое слово ( [) - это команда, а остальные - ее позиционные аргументы. Есть оставшиеся аргументы после первого] .

Также нет, [[это действительно ключевое слово Bash, но в этом случае оно анализируется только как обычный аргумент команды, потому что оно не находится в начале команды.

Джо Со
источник