Меня смущает оценка обратных кавычек в bash. Я видел подобный код раньше, который имеет смысл:
RESULT=`whoami`
Это сохраняет вывод whoami
команда в RESULT
переменной и подтверждает, что обратные кавычки оценивают вывод команды внутри них. Но я также видел такой код:
if `wget google.com -T 2 -t 1 -o /dev/null`; then
echo "Internet ok"
fi
Это проверка подключения к Интернету путем попытки получить домашнюю страницу Google (с -t 1
за одну попытку -T 2
для 2-секундного таймаута и перенаправления на /dev/null
поскольку он на самом деле не хочет вывода, а просто хочет увидеть, удастся ли он). Код читается так, как будто автор ожидал, что обратные кавычки будут оценивать код выхода wget
команда, а не вывод.
Но это действительно работает. Он печатает Internet ok
если он может подключиться к google.com, и если я изменю URL-адрес на какой-то бессмысленный URL-адрес, который не существует, он не удовлетворяет условию if и ничего не печатает. Я не понимаю, почему это работает.
Самостоятельный запуск wget
команда с действительными и недопустимыми URL-адресами ничего не выводит в обоих случаях и отличается только кодом выхода.
Я пришел к выводу, что есть специальная конструкция для if
с последующими обратными кавычками, которые возвращают код выхода, а не результат. Я ошибся?
Нет, обратные кавычки не имеют особого значения, и вы даже можете запустить wget
команда без них в if
заявление.
if
всегда оценивает код выхода следующей команды.
Более полный обзор можно найти Вот.
РЕДАКТИРОВАТЬ
Обратные кавычки инициируют подстановку команд, которая выполняется в подоболочке и возвращает код выхода. if
просто проверяет коды возврата, вывод команды не используется.
Чтобы сравнить вывод команды, вы можете использовать [
, который должен быть закрыт ]
, что по сути является тестом. Тест может быть любым
man test
сравнение строк
[ "hello" == "test" ]
целочисленный тест
[ 2 -eq 3 ]
Если тест завершится успешно, вы получите код выхода 0 (истина), в противном случае не 0 (ложь), который снова оценивается if
.
Итак, вы имеете в виду следующее.
if [ "`wget google.com -T 2 -t 1 -o /dev/null`" == "" ]
then
echo "emptY"
fi
Но это не имело бы особого смысла из-за перенаправления вывода на /dev/null
ты всегда будешь правдой от [ "
wget google.com -T 2 -t 1 -o / dev / null" == "" ]
.
С другой стороны, также было бы бесполезно проверять, есть ли на выходе wget
команда действительно содержит вывод, исключая -o /dev/null
, потому что даже в случае ошибки вы получите результат, но с разными кодами возврата.
В сценариях оболочки bash if в наши дни избегают обратных кавычек и используют подстановку команд $(...)
синтаксис вместо этого.
Он более четкий, чем очень расплывчатые обратные кавычки, и поддерживает вложение, что невозможно в обратных кавычках. I.E:
command $(command two $(command three))
Я наконец получил четкий ответ на этот вопрос через ветка обсуждения в списке рассылки bash. Вывод такой:
if
здесь, он просто выполняет команду после if
а затем ветвление на основе кода выхода этой команды. Неожиданное поведение здесь вместо этого приписывается самой подстановке команд.if
или нет не имеет значения).if `cmd` ...
управляет if
тело на основе код выхода из cmd
когда cmd
ничего не пишет в стандартный вывод заключается в том, что существует правило спецификации POSIX о выполнении команд оболочки, которое гласит:Если имя команды отсутствует, но команда содержала подстановку команды, команда должна завершиться статусом выхода последней выполненной подстановки команды. В противном случае команда должна завершиться нулевым статусом выхода.
ссылка: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
cmd
ничего не записывает в stdout, оболочка - вместо того, чтобы выполнять пустую команду - берет код выхода подстановки команды (код выхода cmd
сам) и возвращает его как код выхода родительской команды, которая затем всплывает до if
.Чтобы лучше проиллюстрировать это, посмотрите следующий пример:
$ `true`
$ echo $?
0
$ `false`
$ echo $?
1
Оболочка сначала запускается true
который ничего не передает на стандартный вывод, поэтому результирующая команда пуста. Там, где я ожидал, что пустая команда либо детерминированно завершится успешно, либо не удастся, в соответствии с приведенным выше правилом, она завершается кодом выхода true
а не «код выхода пустой команды».