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

@chepnerが正しい答えをくれました。

ちなみに、このようにコマンドを短くすることもできます (それ以上のシェルは必要ありません)。

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

元のコードでは、渡す二重引用符で囲まれた文字列は/bin/sh、 を呼び出す前にシェルによって処理されますsh。特に、関連するコマンド置換seqとパラメーターの$i両方が拡張されます。その結果、次のようになります (set -xコードを実行する前に呼び出すことで確認できます)。

for i in 1
2
3 ; do echo  ; done

1 に続く改行は、繰り返されるシーケンスの終了として扱われますfor。この時点で、shはキーワード を予期しますdoが、代わりに を参照します2

これを修正する 1 つの方法は、シェルの別のインスタンスに文字列を渡す必要があると仮定してseq、別の区切り記号 (スペースなど) を使用するように指示することです。$i現在のシェルではなく、サブシェルによって評価されるように、ドル記号もエスケープする必要があります。

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

shサブシェルはとにかく理解できない配列を認識しないため、これは で機能します。sudo_O は別の答えを提供します。これには、に渡される文字列全体を保護し、その文字列shに の定義を含めてlist、サブシェルで表示できるようにする必要があります。jordanm で指摘されているように、POSIXは配列をサポートしていないため、shなどのシェルでなければならないことに注意してください。bashsh

于 2013-03-07T15:04:03.313 に答える
0

サブシェルを生成するときに配列listは定義されないため、長さはありません。

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

のように見える:

for i in seq 1 0

見る:

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

出力がseq 1 0生成されないため、結果が表示されません。

list現在のシェルで各値を設定して出力します。

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

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

listまたは、サブシェルで を定義します。

$ 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 に答える