Posix

是否所有 POSIX shell 都以相同的方式實現算術擴展 $((…)) ?

  • May 27, 2020

我正在嘗試編寫一個可以在任何 POSIX shell 下工作的 shell 腳本,我發現dash. 我想知道這是否是我可以依賴於在其他 POSIX 兼容的 shell 下工作的東西,或者它是否只是dashshell 的一個無意的特性。

在算術擴展中,變數可以寫成帶或不帶初始美元符號(位置參數的情況除外,它必須始終寫成美元符號$1$2)。

但是我發現 的行為"$((X))"不同於"$(($X))"似乎"$(($X))"被擴展了兩次,而不僅僅是一次。即,如果我的變數X包含另一個變數的名稱( X=Y),而該變數又包含一個數值 ( Y=1),那麼"$(($X))"將返回1,而"$((X))"只會產生一個“非法數字:Y”錯誤。

我可以依賴其他 POSIX shell 中的這種行為嗎?

奇怪的行為

"$((X))"並且"$(($X))"行為不一樣。

$ X=Y; Y=1
$ echo "$((X))"
dash: 1: Illegal number: Y
$ echo "$(($X))"
1

預期行為

為了完整起見,我在這裡包括沒有間接和兩層間接的內容。沒有間接,一切都按預期工作:

$ X=1
$ echo "$((X))"
1
$ echo "$(($X))"
1

正如預期的那樣,兩層間接不起作用(儘管請注意錯誤消息指的是不同的值)。

$ X=Y; Y=Z; Z=1
$ echo "$((X))"
dash: 6: Illegal number: Y
$ echo "$(($X))"
dash: 7: Illegal number: Z

這個問題與這個關於算術擴展和參數擴展的問題有些相關,但它不一樣,因為它處理的是bash更高級的 shell 的行為,但我想知道預期的 POSIX 行為。

由於您的問題是 POSIX 通用的,並且相關問題似乎涉及更高級的 shell,我將單獨回答這個問題。

您看到的行為來自兩種不同的擴展,參數擴展和算術擴展,POSIX 以該順序指定。和

$ X=Y; Y=1

您的第一個範例僅使用算術擴展:

$ echo "$((X))"

試圖將X的值解釋為算術表達式,但失敗了,因為“Y”不是數字。

您的第二個範例同時使用:

$ echo "$(($X))"

展開(參數展開)為

$ echo "((Y))"

然後算術擴展使用Y’ 值 1。

另請參閱了解在算術表達式和Bash中使用間接擴展進行變數擴展的兩個範例:算術擴展、參數擴展和逗號運算符等。

引用自:https://unix.stackexchange.com/questions/589315