Я хочу знать, в чем именно разница между
a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )
Все 4 присваивают переменной a значение 2, но в чем разница?
Из того, что я нашел Пока что expr медленнее, потому что это не фактическая встроенная оболочка. Но не более того.
Все они имеют дело с арифметикой, но по-разному и переменная создается через различные средства. Некоторые из них характерны для bash
оболочки, в то время как другие не.
$((...))
назван арифметическим расширением, которое типично для bash
и ksh
оболочки. Это позволяет делать простую целочисленную арифметику, никакой материал с плавающей точкой все же. Результат выражения заменяет выражение, как в echo $((1+1))
стал бы echo 2
((...))
упоминается как арифметическая оценка и может использоваться в качестве части if ((...)); then
или while ((...)) ; do
операторы, но не работают на присвоения, где как арифметическое расширение $((..))
заменяет выводом операции и может использоваться для присвоения переменных в i=$((i+1))
но не может использоваться в условных операторах.$[...]
старый синтаксис для арифметического расширения, которое удерживается от использования.См. также. Это было, вероятно, сохранено так, чтобы старым bash
сценарии не повреждаются. Это не работало в ksh93
, таким образом, мое предположение - то, что этот синтаксис является определенным для удара.Примечание: пробелы очень важны здесь; не путать $[1+1]
с материалом как [ $a -eq $b ]
. [
с пробелами известен как test
команда, и Вы обычно видите его в частях принятия решений. Это очень отличается в поведении и цели. let
a bash
и ksh
ключевое слово, которое допускает переменное создание с простой арифметической оценкой. При попытке присвоить строку там как let a="hello world"
Вы получите синтаксическую ошибку. Работы в bash
и ksh93
.$(...)
замена команды, где Вы буквально берете вывод команды и присваиваете переменной. Ваша команда здесь expr
, который берет позиционные параметры, как expr arg1 arg2 arg3
, таким образом, пробелы важны. Это - вид подобных маленький калькулятор командной строки для целочисленной арифметики плюс некоторый истинный/ложный и regex тип материала. Это - нейтральная в отношении оболочки команда.Также стоит отметить, что арифметическая замена расширения и команды указана стандартом POSIX, в то время как let
и $[...]
не.
let
команда выполняет арифметическую оценку и является встроенной оболочкой.
Выполните эту команду, и Вы добираетесь, ничто (только оценивает):
let 1+2
$(( ))
используется для выполнения арифметического расширения: читайте здесь
Выполните этого, и Вы получите ошибку (из-за расширения):
$((1+2))
$[ ]
старый синтаксис для арифметического расширения:
Старый $ формата [выражение] удерживается от использования и будет удален в предстоящем из удара. Страница справочника Bash
expr
двоичная команда, если Вы хотите сделать арифметическое расширение в подситуации с командой, можно использовать его:
echo $(expr 1 + 2)
echo `expr 1 + 2`
Начиная с некоторых ответов выше конкретно упоминания ksh93
стоит отметить, что это может сделать математические операции с плавающей точкой, например:
$ print $((1.0/3))
0.333333333333333333
Можно управлять точностью вывода с printf, например:
$ printf "%.4f\n" $((1.0/3))
0.3333
По крайней мере один аргумент должен быть указан как число с плавающей запятой как выше. Если оба указаны как целые числа затем, только целочисленная математика сделана, например:
$ print $((1/3))
0
Это может быть полезно при необходимости в математических операциях с плавающей точкой в сценарии оболочки, так как можно постараться не называть внешнюю команду.
let
не работает в кроне. Я думаю, что это происходит из-за let
наличие его собственной среды. Использовать $((...))
так как это - POSIX. Например,
let x=1+2
echo x=$x
в кроне, результатах в "x =", но "x=3", когда выполнено от оболочки.
x=$((1+2))
echo x=$x
результаты в "x=3" во всех случаях.