我有一個關於 bash 的參數擴展的問題,在逗號表達式內,在算術表達式內。我有兩個我認為應該是等價的陳述,但它們不是。
為什麼 bash 行
n=3; k=10; echo $((n++,k=$n))
輸出3
而不是4
? (如我所料,它設置n
為,但設置為。)4
k
3
相反,bash 行
n=3; k=10; echo $((n++,k=n))
輸出4
,正如我所料。 (它設置n
為4
,並且也k
設置為4
。)
我嘗試在兩個 bash 行中取代n++
with ++n
、 withn=n+1
和 with n=$((n+1))
,它們都會產生相同的差異:在所有腳本中k=$n
產生,在所有腳本中產生。3
k=n
4
我的理解是,如果 的值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
]