2

我做错了什么?

unset list
list=("A" "B" "C")
/bin/sh -c "for i in `seq 1 ${#list[@]}` ; do echo $i ; done "

它应该返回:

1
2
3

代替:

/bin/sh: -c: line 1: syntax error near unexpected token `2'
/bin/sh: -c: line 1: `2'
4

3 回答 3

2

在您的原始代码中,您传递给的双引号字符串/bin/sh在调用sh. 特别是,涉及的命令替换seq和参数$i都被扩展了。结果,您得到以下信息(您可以set -x在运行代码之前通过调用来确认):

for i in 1
2
3 ; do echo  ; done

1 之后的换行符被视为for将迭代的序列的终止。此时,sh会期望关键字do,但会看到2

解决此问题的一种方法是,假设您确实需要将字符串传递给 shell 的另一个实例,即告诉seq使用不同的分隔符(例如空格)。您还需要转义美元符号,$i以便它由子 shell 评估,而不是当前 shell。

unset list
list=("A" "B" "C")
/bin/sh -c "for i in `seq -s' ' 1 ${#list[@]}` ; do echo \$i ; done "

这将适用于sh,因为子shell 看不到数组,无论如何它都不会理解。sudo_O 提供了一个不同的答案,它涉及保护传递给的整个字符串sh,并包括该list字符串中的定义,以便它在子shell中可见。请注意,您sh必须是 shell,例如bash,因为 POSIXsh不支持数组,正如 jordanm 所指出的那样。

于 2013-03-07T15:04:03.313 回答
2

@chepner 给了你正确的答案。

顺便说一句,您也可以像这样缩短命令(不涉及进一步的 shell)

unset list
list=("A" "B" "C")
for i in `seq 1 ${#list[@]}` ; do echo $i ; done
于 2013-03-07T15:21:50.497 回答
0

list生成子shell时不会定义 数组,因此它没有长度:

for i in `seq 1 ${#list[@]}`

被视为:

for i in seq 1 0

看:

$ sh -c 'echo ${#list[@]}'
0

并且seq 1 0不产生任何输出,因此看不到任何结果。

list在当前 shell 中设置并打印出每个值:

$ list=("A" "B" "C")

$ for i in `seq 1 ${#list[@]}`;do echo $i;done
1
2
3

或者list在子shell中定义:

$ sh -c 'list=("A" "B" "C");for i in `seq 1 ${#list[@]}`;do echo $i;done'
1
2
3
于 2013-03-07T15:06:58.837 回答