for迴圈語法

for迴圈語法

為什麼

for i in {1..5}; do x="${i}" echo "$x"; done

不輸出

1
2
3
4
5

這樣做的正確方法是什麼?

(已測試for i in {1..5}; do x=$(i) echo "$x"; done

-bash: i: 未找到指令

和別的)

答案1

按要求回答您的問題

為什麼不for i in {1..5}; do x="${i}" echo "$x"; done輸出1、、、、?2345

原因與執行期間評估操作的順序有關。看看這個指令

x="${i}" echo "$x"

這是做什麼的

  1. 用變數的值替換變數
  2. 為變數分配臨時值x
  3. 執行命令

所以你得到

  1. x=1 echo ""(或x=2 echo "",等等)
  2. 在此命令的持續時間內,x設定為值1
  3. 執行命令:echo ""

您可能認為該指令是兩個指令:為 賦值x,輸出其值。但在 shell 語法中,您編寫的程式碼是完全合法的,因此 shell 會毫無異議地執行它。

答案2

您要求回答兩個問題:

  1. 您要求解釋為什麼當前程式碼沒有產生預期的輸出。

  2. 您詢問了編寫程式碼的正確方法,以便它確實產生預期的輸出。

查看您的程式碼,我可以看到兩種可能的解釋來解釋為什麼您以這種方式編寫程式碼:

  1. 可能會有一些輕微的混亂for迴圈的語法

  2. 在所謂的評估順序中可能存在一些輕微的混亂簡單的指令

for迴圈語法

在第一種情況下,我會說你在變數賦值後缺少一個分號。如果您想將 for 迴圈寫在一行上,那麼您需要在迴圈體中的每個指令後面放置一個分號。試試這個:

for i in {1..5}; do x="${i}"; echo "$x"; done

另一個選擇是使用多行語法編寫 for 循環,並用換行符號代替分號:

for i in {1..5}
do
x="${i}"
echo "${x}"
done

您也可以混合搭配分號和換行符,例如:

for i in {1..5}; do
x="${i}"; echo "${x}"
done

評估簡單指令

在第二種情況下,我想說您可能假設命令序言中的變數賦值(即賦值x="$i")發生在命令主體中的變數擴展(即${x}in的擴展echo "${x}")之前。但事實並非如此。為了驗證這一點,我們可以參考頁面簡單的命令擴展在 Bash 手冊中或關於簡單指令的小節在裡面POSIX規範。這兩篇參考文獻都包含以下段落:

「簡單命令」是一系列可選的變數分配和重定向,可以任意順序,可選地後跟單字和重定向,並由控制運算子終止。

當需要執行給定的簡單命令時(即,當任何條件結構(例如 AND-OR 清單或案件語句沒有繞過簡單命令),以下擴展、賦值和重定向都應從命令文字的開頭到結尾執行:

  1. 根據以下規則被識別為變數賦值或重定向的單詞Shell 語法規則儲存以供步驟 3 和 4 的處理。

  2. 不是變數賦值或重定向的單字應該被擴展。如果擴充後仍有任何字段,則第一個字段應被視為命令名稱,其餘字段是命令的參數。

  3. 重定向應按中所述執行重定向

  4. 每個變數賦值都應在賦值之前進行擴展,以進行波形符號擴展、參數擴展、命令替換、算術擴展和引號刪除。

請注意,步驟 2 是指令中發生變數擴充的地方,但步驟 1 告訴我們變數賦值會一直儲存到步驟 3 和echo "${x}"4 。這解釋了為什麼您得到空輸出。echo ""x="${i}"

有關此主題的進一步討論,請參閱以下帖子:

答案3

在 中,使用, Bourne 運算子的zsh第三種${var::=value}形式,其中賦值是無條件的(而不是僅當 var 未設定/為空時)。${var=value}${var:=value}

for i in {1..5}; do echo ${x::=$i}; done

或者:

for i ({1..5}) echo ${x::=$i}

bash

set -o posix # so the value of x remains after eval returns
for i in {1..5}; do x=$i eval 'echo "$x"'; done

也就是說,您需要$x在評估包含其擴充功能的程式碼時進行設定。

對於像這裡這樣的十進制整數值,您還可以執行以下操作:

for i in {1..5}; do echo "$((x = i))"; done

或者,您始終可以${var:=value}在設定x為空字串後使用 Bourne 運算子。

for i in {1..5}; do x=; echo "${x:=$i}"; done

相關內容