Shell-Script

如何在 POSIX shell 腳本中創建算術循環?

  • February 7, 2022

我知道如何forbash.

如何在 POSIX shell 腳本中執行等效循環?

由於有多種方法可以實現相同的目標,請隨意添加您自己的答案並詳細說明它的工作原理。

一個這樣的bash循環的範例如下:

#!/bin/bash
for (( i=1; i != 10; i++ ))
do
   echo "$i"
done

我在Shellcheck.net wiki中找到了有用的資訊,我引用:

  1. 重擊¹:
for ((init; test; next)); do foo; done
  1. POSIX:
: "$((init))"
while [ "$((test))" -ne 0 ]; do foo; : "$((next))"; done

雖然要注意i++不是 POSIX,所以必須翻譯,例如 to i += 1or i = i + 1

:是一個始終具有成功退出程式碼的空命令。"$((expression))"是作為參數傳遞給 的算術擴展:。您可以在算術擴展中分配給變數或進行算術/比較。


因此,問題中的上述腳本可以使用以下規則以 POSIX 方式重寫:

#!/bin/sh
: "$((i=1))"
while [ "$((i != 10))" -ne 0 ]
do
   echo "$i"
   : "$((i = i + 1))"
done

雖然在這裡,您可以通過以下方式使其更清晰:

#!/bin/sh
i=1
while [ "$i" -ne 10 ]
do
   echo "$i"
   i=$((i + 1))
done

如在 中init,我們分配了一個常量值,因此我們不需要計算算術表達式。i != 10in可以很容易地test轉換為[表達式,並且 fornext使用 shell 變數賦值而不是算術表達式中的變數賦值,讓我們擺脫:了引用的需要。


除了i++->之外i = i + 1,還有更多非 POSIX 的特定於 ksh/bash 的結構的翻譯,您可能需要這樣做:

  • i=1, j=2. 算術運算符不是真正的POSIX,(並且在某些使用 ksh93 的語言環境中與小數分隔符衝突)。您可以將其替換為像+in這樣的另一個運算符,: "$(((i=1) + (j=2)))"但使用i=1 j=2會更清晰。
  • a[0]=1: POSIX shell 中沒有數組
  • i = 2**20: POSIX shell 語法中沒有冪運算符。<<雖然支持 2 的冪,但可以使用i = 1 << 20. 對於其他權力,可以訴諸bci=$(echo "3 ^ 20" | bc)
  • i = RANDOM % 3: 不是POSIX。POSIX 工具箱中最接近的是i=$(awk 'BEGIN{srand(); print int(rand() * 3)}').

¹ 從技術上講,該語法來自 ksh93 shell,除了 bash 之外,zsh 也可以使用

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