我知道如何for
在bash
.
如何在 POSIX shell 脚本中执行等效循环?
由于实现同一目标的方法有多种,请随意添加您自己的答案并详细说明其工作原理。
此类循环的示例bash
如下:
#!/bin/bash
for (( i=1; i != 10; i++ ))
do
echo "$i"
done
答案1
我在以下位置找到了有用的信息Shellcheck.net 维基, 我引用:
重击 1:
for ((init; test; next)); do foo; done
POSIX:
: "$((init))" while [ "$((test))" -ne 0 ]; do foo; : "$((next))"; done
但请注意,这i++
不是 POSIX,因此必须进行翻译,例如转换为i += 1
或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
,我们分配一个常量值,因此不需要计算算术表达式。 in可以很容易地转换为表达式,而 for使用 shell 变量赋值而不是算术表达式内的变量赋值,让我们摆脱了i != 10
引用的需要。test
[
next
:
除了i++
->之外i = i + 1
,您可能还需要对 ksh/bash 特定结构进行更多非 POSIX 翻译:
i=1, j=2
。算术,
运算符不是真的POSIX(并且在某些区域设置中与 ksh93 的小数分隔符发生冲突)。您可以将其替换为另一个运算符,例如+
,: "$(((i=1) + (j=2)))"
但使用i=1 j=2
会更清晰。a[0]=1
: POSIX shell 中没有数组i = 2**20
: POSIX shell 语法中没有幂运算符。<<
但支持 2 的幂,因此可以使用i = 1 << 20
.对于其他权力,可以诉诸bc
:i=$(echo "3 ^ 20" | bc)
i = RANDOM % 3
: 不是 POSIX。 POSIX 工具箱中最接近的是i=$(awk 'BEGIN{srand(); print int(rand() * 3)}')
.
1 从技术上讲,该语法来自 ksh93 shell,除了 bash 之外,还可以在 zsh 中使用
答案2
感谢您对上述差异的深入背景知识。使用 shellcheck.net 时对我有用的替代品如下。
巴什
for i in {1..100}; do
...
done
POSIX
i=1; while [ $i -le 100 ]; do
...
i=$(( i + 1 ))
done
有些人指出 seq 也是使用 seq 1 10 的选项。创建一个循环,但这取决于 os 有 seq.
答案3
这种方法更加通用,因为您可以$
在其中插入任意变量:
#!/bin/sh
for i in $(seq 1 10); do
echo $i
done
只需确保您已seq
安装实用程序,但由于它位于 中CoreUtils
,因此您已安装。