2014-03-28 66 views
1

我在使用bash執行某些命令時遇到了問題。比方說,我有一個簡單的bash腳本:在帶有空格參數的bash中執行命令

#!/bin/bash 
cmd="sh -c \"ls\"" 
$cmd 

這工作都很好。但是,如果我改變了命令的參數包含空格:

#!/bin/bash 
cmd="sh -c \"ls -a\"" 
$cmd 

則拋出-a": 1: -a": Syntax error: Unterminated quoted string錯誤。看來,bash正確地注意到了開放報價,但它停止在第一空間尋找結束報價。如果我將$cmd更改爲echo $cmd,則會按預期返回sh -c "ls -a"。如果我在終端執行這個命令,一切正常,但是$(./mysh.sh)失敗,出現同樣的錯誤。

我試過用\逃脫空間,或用\\\"(愚蠢的想法,但值得一試)「雙重逃脫」引號。任何人都可以解釋這裏發生了什麼?

+2

http://mywiki.wooledge.org/BashFAQ/050 – user000001

回答

5

你會更好的存儲功能命令:

cmd() { 
    sh -c "ls -a" 
} 
cmd 

或者在陣列:

cmd=(sh -c "ls -a") 
"${cmd[@]}" 

使用普通字符串變量是行不通的。你必須使用eval,這是not a great idea。功能要好得多。

cmd="sh -c \"ls -a\"" 
eval "$cmd" 
+0

謝謝 - 你能解釋爲什麼eval不是一個好的選擇? – BroiSatse

+2

@BroiSatse:至於爲什麼'eval'通常不是一個好主意_security_的原因:它允許_any_命令存儲在一個字符串中執行 - 如果字符串交給你,你必須相信它的內容只做你期望它。 'eval'在有限和受控的情況下可能會很好,但通常最好遠離(並且通常有更好的選擇,如在這種情況下) - 參見http://mywiki.wooledge.org/BashFAQ/048 – mklement0

+0

@ mklement0優秀的答案。這比我寫的要好。 –

0
cmd="sh -c \"ls -a\"" 
eval $cmd 
3

重複引用規則的應用可能非常複雜。首先,我將解釋什麼錯誤:

cmd="sh -c \"ls -a\"" 
$cmd 

的第一件事情執行$ cmd是分裂它的空格字符時擊的作用:讓你得到三個參數的命令,等價於:

sh -c "\"ls" "-a\"" 

已經可以看到哪裏出錯了。一些解決方案已經公佈,但一般的shell命令的每一級處理該命令將受到,您需要提供的警衛字符另一個層面保持原有的本意:

# To execute the command "ls -a" in a shell: 
sh -c "ls -a" 
# Two shells deep: 
sh -c "sh -c ls\\ -a" # Backslash protects space from being treated as an argument separator by first level of shell processing 

這是更好地避免如果你可以重複報價守護的應用...