`((...))`与`(...)`有什么不同?

时间:2015-09-26 09:23:34

标签: shell unix switch-statement arithmetic-expressions subshell

我写了以下代码:

case "$2"  in  '+') ((res = $1 + $2 ));;

               '-') ((res = $1 - $2 ));;
esac

echo $res

用法示例:./"*filename*" 2 + 3

如果我使用双括号,

((res = $1 + $2 ))

然后打印结果。但是,如果我使用单个括号

(res = $1 + $2 )

然后什么都没打印出来。 ( )(( ))之间有什么区别?

1 个答案:

答案 0 :(得分:2)

双括号(( ... ))用于arithmetic expansion,而单括号( ... )subshell中运行封闭的命令,{{3}}具有自己的范围并且不具有&#39}。 t影响其父shell的环境。

此处,对于(res = $1 + $2),即使变量res在子shell中成功分配了值,res仍会在父shell中取消设置,这就解释了为什么没有打印任何内容。在这种特殊情况下,您希望使用(( ... ))

此外,请注意,在您的示例中,第二个参数$2是运算符,而不是第二个操作数。因此,您需要使用((res = $1 + $3))((res = $1 - $3))

此外,为了提高稳健性,您可能需要确保

  • 参数的数量有效,
  • 第一个和第三个参数是有效整数,
  • 第二个参数是一个有效的算术运算符(+-,这里),

最后,为了提高不同shell的可移植性,请优先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