Я думаю, что рекомендация, которую вы видели, была для POSIX sh и / или testкоманды, которая удваивается как [команда, а не как [[конструкция, которая появилась в ksh (спасибо Stéphane Chazelas за подсказку), а также используется, например, в bash, zsh и некоторых других снаряды.
В большинстве языков, таких как C, когда условие уже известно как истинное или ложное, нет необходимости оценивать оставшиеся части в зависимости от операции: если true не после логической или следующей за ней, если false не после логической и , и т.д. Это, конечно, позволяет, например, остановиться, когда указатель равен NULL, и не пытаться разыменовать его в следующем предложении.
Но ш «s [ expr1 -o expr2 ]конструкция (включая реализацию в Bash) не делает этого: он всегда оценивает обе стороны, когда один хотел бы только выражение1 быть оценены. Это могло быть сделано для совместимости с testреализацией команды. С другой стороны, sh ||и &&действительно следуют обычному принципу: не оценивается, если это не изменит результат.
Таким образом, разница в примечании будет:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
что дает:
true
or-was-evaluated
Выше каждый [мог быть заменен /usr/bin/[на псевдоним testкоманды, который использовался до того, как [был встроен в оболочку.
Пока две следующие конструкции:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
или
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Будет только уступать trueи оставлять effectпустым: ||ведет себя правильно, и [[исправил эту проблему тоже.
ОБНОВИТЬ:
Как прокомментировал @ StéphaneChazelas, я пропустил несколько различий, связанных с первоначальным вопросом. Я просто поставлю здесь самый важный (по крайней мере для меня): приоритет операторов.
Пока оболочка не будет учитывать приоритет:
if true || true && false; then
echo true
else
echo false
fi
Выход (потому что нет приоритета и, следовательно, сначала true || trueоценивается, а затем && false):
false
внутри [[ ]]на &&оператора имеет приоритет над ||:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
Урожай (потому что 1 -eq 1 && 1 -eq 0он сгруппирован и, следовательно, является вторым членом ||):
true
по крайней мере для кш , баш , зш .
Так [[ ]]улучшилось поведение как [ ]логических операторов прямой, так и логической оболочки.
[илиtest( не[[), найдитеOBтеги (связанные с «устаревшим» определением) в спецификации POSIXtest. Вtest, есть некоторые патологические случаи , когда это может быть невозможно сказать , если(или)предназначается , чтобы быть синтаксисом смысл команды испытаний или строки , которые будут проверены, так что люди , которые игнорируют маркеры устаревания и использовать этот синтаксис может фактически нужен otherwise- устаревшая"x$foo"практика; с[[, это не проблема.