2014-10-03 69 views
0

我試圖執行以下命令:第二個命令之前猛砸符號化引用字符串用空格作爲單個單詞

ls: 'my: No such file or directory 
ls: dir': No such file or directory 

使用「設置-x」:

mkdir 'my dir' 
CMD="ls 'my dir'" 
RESULT=$($CMD) 

這導致顯示實際發出的命令是:

++ ls ''\''my' 'dir'\''' 

這顯然是從我的交流中抽象出來的試着去做;這個代碼本身並不起任何作用。但我的問題是爲什麼bash將引用的字符串標記爲這樣以及如何讓它停止?

+2

查看BashFAQ#50:http://mywiki.wooledge.org/BashFAQ/050 – 2014-10-03 22:03:32

+0

謝謝,這非常有幫助。 – cameronhimself 2014-10-03 22:27:43

+0

另請參閱[BashFAQ#48](http://mywiki.wooledge.org/BashFAQ/048)。正如GreyCat所說,「eval」是一種常見的「邪惡」拼寫錯誤。 :) – 2014-10-04 07:39:34

回答

3

(幾乎)所有語言分離代碼和數據:

args="1, 2" 
myfunc(args) != myfunc(1, 2) 

相同在bash中是真實的。將單引號放在文字字符串中不會使bash解釋它們。

存儲程序名和參數(又名一個簡單的命令)的正確方法是使用數組:

cmd=(ls 'my dir') 
result=$("${cmd[@]}") 

bash將在空間,除非你雙引號,這就是爲什麼你的榜樣有時會自動拆分單詞似乎工作。這是令人驚訝和容易出錯的,除非你有充分的理由不要,否則你應該總是雙引號。

也可以使用eval讓bash將字符串解釋爲完全使用bash代碼。這是經常推薦的,但幾乎總是錯誤的。

-1

解決方案1:使用sh -c

mkdir 'my dir' 
CMD="ls 'my dir'" # careful: your example was missing a ' 
RESULT=$(sh -c "$CMD") 

解決方案2:聲明CMD作爲數組

mkdir 'my dir' 
CMD=(ls 'my dir') # array with 2 elements 
RESULT=$("${CMD[@]}") 
+2

-1:「解決方案1」與使用'eval'完全相同,只是它不允許您在父進程中更改變量,具有執行子進程的所有開銷,並將shell從bash切換到在該子命令的持續時間內,本地安裝的POSIX sh解釋器。 – 2014-10-03 22:02:35