Двойные скобки ((...))
предназначены для arithmetic expansion, в то время как одиночные скобки (...)
запустить прилагаемую команду в subshell, которая имеет свою собственную сферу и не влияет на окружающую среду своей родительской оболочки.
Здесь с (res = $1 + $2)
, даже если переменная res
успешно присвоено значение в субоболочке, res
остается неустановленным в родительской оболочке, что объясняет, почему ничего не печатается. Вы хотите использовать ((...))
, в данном конкретном случае.
Кроме того, обратите внимание, что в вашем примере второй параметр, $2
, является оператором, а не вторым операндом. Соответственно, вам нужно вместо этого использовать ((res = $1 + $3))
и ((res = $1 - $3))
.
Кроме того, для надежности, вы можете убедиться, что
- количество аргументов, действительно,
- первые и третьи аргументами являются допустимыми целыми числами,
- второго параметра является допустимым арифметический оператор (
+
или -
, здесь),
- т.д.
Наконец, для улучшения переносимости в разных оболочках предпочтительнее printf
по сравнению с echo
.
уточнена и доработана код
#!/bin/sh
# foo
# Custom error function
die() {
printf "%s\n" "$1" 1>&2 ;
exit 1;
}
# Function that returns an exit status of
# 0 if its first argument is a valid integer,
# 1 otherwise.
is_integer() {
[ "$1" -eq 0 -o "$1" -ne 0 ] >/dev/null 2>&1
}
# Check that the number of argument is 3
[ "$#" -eq 3 ] || die "invalid number of arguments"
# Check that the operands are valid integers
is_integer "$1" || die "invalid first operand"
is_integer "$3" || die "invalid second operand"
# If the second argument is a valid operator, assign res accordingly;
# otherwise, die.
case "$2" in
'+')
((res = $1 + $3))
;;
'-')
((res = $1 - $3))
;;
*)
die "invalid operator"
;;
esac
printf "%s\n" "$res"
Тесты
После создания сценария (так называемый "Foo") исполняемый файл, запустив
chmod u+x foo
Я получаю следующие результаты
$ ./foo -18 + 5
-13
$ ./foo 9 - 4
5
$ ./foo a + 2
invalid first operand
$ ./foo -18 + c
invalid second operand
$ ./foo 3/4
invalid operator
Какая оболочка вы с помощью? – melpomene
'((...))' для [арифметического расширения] (http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_04), тогда как '(...)' запускает вложенную команду в подоболочку, которая не влияет на ее родительскую оболочку. – Jubobs
Также обратите внимание, что в вашем примере вторым параметром ('$ 2') является оператор, а не второй операнд. Соответственно, вы, вероятно, хотите '((res = $ 1 + $ 3))' и '((res = $ 1 - $ 3)), здесь. – Jubobs