我无法理解使用时需要转义的内容sh -c
。
假设我想运行 for 循环for i in {1..4}; do echo $i; done
。就其本身而言,这工作得很好。如果我将它传递给eval
,我需要转义$
: eval "for i in {1..4}; do echo \$i; done"
,但我不能让它工作sh -c "[...]"
:
$ sh -c "for i in {1..4}; do echo $i; done"
4
$ sh -c "for i in {1..4}; do echo \$i; done"
{1..4}
$ sh -c "for i in \{1..4\}; do echo \$i; done"
{1..4}
$ sh -c "for i in \{1..4\}\; do echo \$i\; done"
sh: 1: Syntax error: end of file unexpected
我在哪里可以找到有关此的更多信息?
答案1
-c
通常的做法是在单引号内定义脚本(在 后面)。您需要使用的另一部分是一个外壳,其中{1..4}
构造有效:
$ bash -c 'for i in {1..4}; do echo $i; done' # also work with ksh and zsh
让它与 dash (你的sh
)一起工作的一种替代方法是在你正在交互使用的 shell 上进行扩展(我假设你使用 bash 或 zsh 作为你的交互式 shell):
$ dash -c 'for i do echo $i; done' mysh {1..4}
1
2
3
4
答案2
{1..4}
csh
是一个 zsh 运算符,从的大括号扩展运算符扩展而来,{x,y}
现在其他一些 shell 支持,但它不是 POSIX sh 运算符(直到最近,POSIX 实际上甚至必需的 echo {1..4}
来输出{1..4}
)。
即使在 zsh 或现在支持的其他 shell 中{x..y}
,这也不是执行递增整数变量的循环的最佳方法,因为您最终会分配所有值的列表(此处仅分配 4 个值,但扩展性不佳)。for i in $(seq 4)
(seq
存在不是标准命令)除了依赖于 的当前值之外,也存在同样的问题$IFS
。
在 ksh93、bash、zsh 中,使用:
for (( i = 1; i <= 4; i++ )); do
printf '%s\n' "$i"
done
一般认为比较好。它还允许负值,并且可以更好地控制索引的增量方式。
该{x..y}
方法的优点是允许在多个范围内循环,或在字母上循环,或使用填充(尽管根据 shell 及其版本有所不同):
for i in {1..5} {9..12} x{0..3} {f..p} {001..0010}; do
...
done
在 中zsh
,另请参阅:
i=; repeat 4 printf '%s\n' $((++i))
在 POSIX 中sh
,你会这样做:
i=1; while [ "$i" -le 4 ]; do
printf '%s\n' "$i"
i=$(( i + 1 ))
done
或者:
sh -c '
i=1; while [ "$i" -le 4 ]; do
printf "%s\n" "$i"
i=$(( i + 1 ))
done'
如果您需要新的sh
调用,请从另一个 Bourne/rc/fish 之类的 shell 中运行该循环。
当然,在这里,你也可以这样做:
for i in 1 2 3 4; do
printf '%s\n' "$i"
done