我做错了什么?
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'
答案 0 :(得分:2)
在原始代码中,传递给/bin/sh
的双引号字符串在调用sh
之前由shell处理。特别是,涉及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
必须是bash
之类的shell,因为POSIX sh
不支持数组,正如jordanm所指出的那样。
答案 1 :(得分:2)
@chepner给了你正确的答案。
顺便说一句,你也可以像这样缩短命令(不再涉及shell)
unset list
list=("A" "B" "C")
for i in `seq 1 ${#list[@]}` ; do echo $i ; done
答案 2 :(得分:0)
当您生成子shell时,将不会定义数组list
,因此它不会产生长度:
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
或者在子shell中定义list
:
$ sh -c 'list=("A" "B" "C");for i in `seq 1 ${#list[@]}`;do echo $i;done'
1
2
3