【问题标题】:How is `(( ... ))` different from `( ... )`?`(( ... ))` 与 `( ... )` 有何不同?
【发布时间】:2015-12-24 01:51:31
【问题描述】:

我写了以下代码:

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

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

echo $res

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

如果我使用双括号,

((res = $1 + $2 ))

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

(res = $1 + $2 )

然后什么都不会打印。 ( )(( ))有什么区别?

【问题讨论】:

  • 你使用的是哪个外壳?
  • ((...)) 用于arithmetic expansion,而(...) 在子shell 中运行封闭的命令,这不会影响其父shell。
  • 另外,请注意,在您的示例中,第二个参数 ($2) 是运算符,而不是第二个操作数。因此,您可能需要((res = $1 + $3))((res = $1 - $3)),在这里。
  • @Jubobs 这些 cmets 可以作为答案发布。
  • 看看shell手册怎么样?它解释了( ... )(( ... ))。在 Linux 上可能是 man bash

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


【解决方案1】:

双括号(( ... )) 用于arithmetic expansion,而单括号( ... )subshell 中运行封闭的命令,它有自己的范围,不会影响其父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

【讨论】:

  • 为使用 printf 而不是 echo 鼓掌。
猜你喜欢
  • 1970-01-01
  • 2013-01-31
  • 2020-05-28
  • 2018-02-04
  • 2021-06-28
  • 2010-10-13
  • 2011-03-21
  • 2012-03-25
相关资源
最近更新 更多