2011-01-12 86 views

回答

67

在執行它們之前,Unix shell對每一行輸入進行一系列轉換。對於大多數貝殼,它看起來是這樣的(從bash手冊頁拍攝):

  • 初始分詞
  • 括號擴展
  • 波浪線擴展
  • 參數,變量和算術擴展
  • 命令替代
  • 二級分詞
  • path e xpansion(又名通配符)
  • 引用刪除

使用$cmd直接得到它通過你的命令中的參數擴展階段置換後,它經歷了所有的下列轉換。

使用eval "$cmd"什麼也不做,直到引用刪除階段,其中$cmd原樣返回,並作爲參數傳遞給eval,其功能是在執行前重新運行整個鏈條通過。

所以基本上,它們在大多數情況下是相同的,並且在您的命令使用參數擴展的轉換步驟時會有所不同。例如,使用支架擴展:

$ cmd="echo foo{bar,baz}" 
$ $cmd 
foo{bar,baz} 
$ eval "$cmd" 
foobar foobaz 
+5

如何在不寫'eval'的情況下執行'eval'$ cmd''$($ cmd)'?'$ {$ cmd}'? –

+2

@StevenLu,其中沒有一個是等價的 - 故意如此:'eval '操作將數據解析爲語法;因此它非常安全敏感,並且隱含地執行它將是非常糟糕的形式。 –

-2

我覺得宇把`符號在你的變量(帶有〜如果移按下)

+3

這執行命令的輸出,例如,在ls -l的情況下會生成一條消息,如「找不到總」命令「(因爲total ...是ls -l的輸出的一部分,例如)所以這不是你想要的。 –

3

如果你只是做eval $cmd 當我們做cmd="ls -l"(交互式和腳本),我們得到的預期的結果。在你的情況下,你有一個grep沒有模式的管道,所以grep部分將失敗並帶有錯誤消息。只要$cmd會產生一個「找不到的命令」(或某些這樣的)消息。 因此,請嘗試使用eval並使用完成的命令,而不是生成錯誤消息的命令。

+0

這只是錯誤打印。應該是「grep exception」。 –

+0

然後使用eval,而不是$ cmd本身,因爲它可能不起作用(它在我的測試中並沒有在bash和zsh下),這就是eval的意思。 –

相關問題