
Я вижу, что я могу сделать
$ [ -w /home/durrantm ] && echo "writable"
writable
или
$ test -w /home/durrantm && echo "writable"
writable
или
$ [[ -w /home/durrantm ]] && echo "writable"
writable
Мне нравится использовать третий синтаксис. Они эквивалентны во всех отношениях и для всех отрицательных и крайних случаев? Есть ли какие-либо различия в переносимости, например, между bash на Ubuntu и на OS X или более старыми/новыми версиями bash, например, до/после 4.0, и расширяют ли они выражения одинаково?
решение1
Да, есть различия. Наиболее переносимыми являются test
или [ ]
. Они оба являются частьюtest
Спецификация POSIX.
Конструкция if ... fi
такжеопределено POSIXи должен быть полностью портативным.
Эта [[ ]]
функция ksh
также присутствует в некоторых версиях bash
(все современные), в zsh
и, возможно, в других, но не присутствует в sh
или dash
или различных других более простых оболочках.
Итак, чтобы сделать ваши скрипты переносимыми, используйте [ ]
, test
или if ... fi
.
решение2
[
является синонимом команды test
и одновременновстроенный bashи отдельное командование. Но [[
этоключевое слово bashи работает только в некоторых версиях. Поэтому по соображениям портативности лучше использовать один []
илиtest
[ -w "/home/durrantm" ] && echo "writable"
решение3
Обратите внимание, что [] && cmd
это не то же самое, что if .. fi
строительство.
Иногда его поведение довольно похоже, и вы можете использовать [] && cmd
его вместо if .. fi
. Но только иногда. Если у вас есть более одной команды для выполнения, если условие или вам нужно if .. else .. fi
быть осторожным и следить за логикой.
Пара примеров:
[ -z "$VAR" ] && ls file || echo wiiii
Это не то же самое, что
if [ -z $VAR ] ; then
ls file
else
echo wiii
fi
потому что если ls
произойдет сбой, echo
будет выполнено, чего не произойдет с if
.
Другой пример:
[ -z "$VAR" ] && ls file && echo wiii
это не то же самое, что
if [ -z "$VAR" ] ; then
ls file
echo $wiii
fi
хотя эта конструкция будет действовать так же
[ -z "$VAR" ] && { ls file ; echo wiii ; }
обратите внимание, что ;
после echo стоит слово, которое важно и обязательно должно присутствовать.
Итак, подводя итог вышесказанному, мы можем сказать:
[] && cmd
== если первая команда выполнена успешно, то выполнить следующую
if .. fi
== если условие (которое также может быть тестовой командой), то выполнить команду(ы)
Поэтому для переносимости между [
и [[
используйте [
только.
if
совместим с POSIX. Так что если вам нужно выбрать между [
и if
выбрать, глядя на вашу задачу и ожидаемое поведение.
решение4
Для переносимости используйте test
/ [
. Но если вам не нужна переносимость, ради вашего спокойствия и спокойствия других, читающих ваш скрипт, используйте [[
. :)
Также см. What is the difference between test, [ and [[ ?
вBashFAQ.