1

我寫以下代碼:「((...))」與「(...)」有什麼不同?

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

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

echo $res 

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

如果使用雙括號,

((res = $1 + $2)) 

則結果被打印。但是,如果我使用單括號

(res = $1 + $2) 

然後沒有打印。 ()(())之間的區別是什麼?

+0

你是哪個外殼使用? – melpomene

+0

'((...))'用於[算術擴展](http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_04),而'(...)'運行封裝在子shell中的命令,它不影響它的父shell。 – Jubobs

+0

此外,請注意,在您的示例中,第二個參數('$ 2')是操作符,而不是第二個操作數。因此,你可能需要'((res = $ 1 + $ 3))'和'((res = $ 1 - $ 3))',這裏。 – Jubobs

回答

2

雙括號((...))arithmetic expansion,而單括號(...)運行在一個subshell封閉命令,它有自己的範圍,並且不影響它的父殼的環境。

這裏,(res = $1 + $2),即使變量res成功分配到子shell的值,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" 

測試

使得腳本後(所謂的 「富」)的可執行文件,運行

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 
+2

掌聲使用printf而不是echo。 – Jens