我在做什麼錯了?在shell命令中使用循環時出現錯誤消息
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'
我在做什麼錯了?在shell命令中使用循環時出現錯誤消息
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'
在你的原代碼,你傳遞給/bin/sh
雙引號的字符串被shell調用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
,因爲POSIX sh
不支持數組,正如jordanm所指出的那樣。
我們的答案以不同的方式解決了這個問題。我讓'seq'命令在當前shell中計算,以便將序列'1 2 3'(不帶換行符)傳遞給子shell。您將'list'的定義移動到子shell中並在其中執行操作。他原來的語法錯誤是由於他傳遞給'/ bin/[ba] sh'的字符串包含嵌入的換行符,導致'for'循環被錯誤地解析。用'set -x'運行他的原始代碼來查看問題。 – chepner 2013-03-07 15:34:25
它爲我工作。 – 2013-03-07 15:35:11
陣列時產卵子外殼list
不會被定義,因此它不會有任何長度製作:視爲
for i in `seq 1 ${#list[@]}`
:
for i in seq 1 0
參見:
$ sh -c 'echo ${#list[@]}'
0
和seq 1 0
不產生輸出,因此看不到任何結果。
要麼設置list
並在當前shell打印出的每個值:在子shell
$ 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
@chepner給你正確的答案。
順便說一句,你還可以縮短了命令像這樣(沒有進一步的外殼參與)
unset list
list=("A" "B" "C")
for i in `seq 1 ${#list[@]}` ; do echo $i ; done
我不確定OP是否有很好的理由將命令傳遞給子shell,但這絕對簡單。 – chepner 2013-03-07 15:24:35
如果你在當前的shell中,你不需要擔心換行符,所以只需放下'-s \' – 2013-03-07 15:39:41
@sudo_O這是真的! – 2013-03-07 15:40:41
你確定'sh'是bash的? POSIX'sh'沒有數組。 – jordanm 2013-03-07 15:19:05