문제

What I'm doing wrong?

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

it should return:

1
2
3

instead of:

/bin/sh: -c: line 1: syntax error near unexpected token `2'
/bin/sh: -c: line 1: `2'
도움이 되었습니까?

해결책

In your original code, the double-quoted string you pass to /bin/sh is processed by the shell before calling sh. In particular, both the command substitution involving seq and the parameter $i are expanded. As a result, you get the following (you can confirm by calling set -x before running your code):

for i in 1
2
3 ; do echo  ; done

The newline following 1 is treated as a termination of the sequence that for will iterate over. At this point, sh will expect the keyword do, but it instead sees 2.

One way to fix this, assuming you really need to pass a string to another instance of the shell, is to tell seq to use a different separator (such as a space). You'll need to escape the dollar sign in $i as well so that it is evaluated by the subshell, not the current shell.

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

This will work with sh, because the subshell does not see the array, which it would not understand anyway. sudo_O provides a different answer, which involves protecting the entire string passed to sh, and including the definition of list in that string so that it is visible in the subshell. Note that your sh must be a shell such as bash, since POSIX sh does not support arrays, as pointed out by jordanm.

다른 팁

@chepner gave you the right answer.

By the way, you can also shorten up the command like this (no further shell involved)

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

The array list will not be defined when you spawn the subshell so it will have no length making:

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

seen as:

for i in seq 1 0

See:

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

and seq 1 0 produces no output hence seeing no results.

Either set list and print out each value in the current shell:

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

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

Or define the list in the subshell:

$ sh -c 'list=("A" "B" "C");for i in `seq 1 ${#list[@]}`;do echo $i;done'
1
2
3
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top