Bash:算術擴展、參數擴展和逗號運算符

Bash:算術擴展、參數擴展和逗號運算符

我有一個關於 bash 的參數擴展的問題,在逗號表達式內,在算術表達式內。我有兩個我認為應該是等價的陳述,但它們不是。

為什麼 bash 行

n=3; k=10; echo $((n++,k=$n))

輸出3而不是4? (如我所料,它設置n為,但設置為。)4k3

相反,bash 行

 n=3; k=10; echo $((n++,k=n))

輸出4,正如我所料。 (它設置n4,並且也k設置為4。)

我嘗試在兩個 bash 行中取代n++with ++n、 withn=n+1和 with n=$((n+1)),它們都會產生相同的差異:在所有腳本中k=$n產生,在所有腳本中產生。3k=n4


我的理解是,如果 的值n是一個整數(它確實是),$n並且n在算術表達式中應該具有相同的值。 (由於其(( ... ))構造,這是一個算術表達式。)根據 bash 手冊,在算術求值部分中,在算術表達式中:

   Shell variables are allowed as  operands;  parameter  expansion  is  performed  before  the
   expression  is  evaluated.  Within an expression, shell variables may also be referenced by
   name without using the parameter expansion syntax.

那麼為什麼 bash 的處理方式$n與本例不同n,它到底是如何被評估的呢$n


如果不使用逗號運算符,我無法重複該問題。據我所知,逗號運算子從左到右計算其每個組件子表達式,包括計算每個組件時該組件的所有副作用。逗號表達式的值就是最後計算的分量(最右邊的)的值。


這個問題是在一個更複雜的腳本的背景下出現的,我最終將其範圍縮小到這個簡單的範例來演示該問題。

那麼,我對算術擴充、參數擴充或逗號運算子有什麼誤解?

請注意,我並不是在尋找解決方法,因為我已經有了一個解決方法: with 的版本n$n我的預期工作。我只是想了解 bash 在帶有 的版本中做了什麼$n,以及為什麼它與僅帶有 的版本做了不同的事情n

答案1

發生 shell 參數擴展在計算表達式之前,包括逗號處理

此表達式被視為位於雙引號內,但括號內的雙引號不會被特別處理。表達式中的所有標記都會經歷參數和變數擴展、命令替換和引號刪除。結果被視為要計算的算術表達式。

你可以看到這個

unset n
echo $((n++,k=$n))

錯誤訊息,

bash: n++,k=: syntax error: operand expected (error token is "=")

顯示$n在處理整個算術表達式之前被替換。

在您的情況下,計算的表達式是

n++,k=3

答案2

在 內部$((...)),首先進行擴展,就像使用雙引號一樣,然後評估結果。

因此,在n=3; k=10; echo $((n++,k=$n))(or n=1; echo "$((++n + $n))",不限於,) 中,計算的算術表達式為n++, k=3

在這裡,您需要:

n=3; k=10; echo "$((n++,k=n))"

(另請注意引號,因為算術擴展與 POSIX shell 中其他形式的單字擴展一樣受 split+glob 的約束)。


1,您會發現呼叫數組和關聯數組的一些變化,因為某些 shell 會在包含$((hash[$key]++))時嘗試正確處理$key]

相關內容