2015-02-23 79 views
2

樣品bash腳本逃離文字星號作爲命令

QRY="select * from mysql" 
CMD="mysql -e \"$QRY\"" 
`$CMD` 

我得到的錯誤,因爲*是越來越爲水珠(枚舉)的文件在我的CWD評估的一部分。

我已經看到了談報價回聲輸出的目的,「$ CMD」參考其他職位,但在這種情況下

"$CMD"

抱怨整個文字字符串作爲命令。

如果我

echo "$CMD" 

然後複製/粘貼到命令行中,事情似乎工作。

+0

'\ *'或者用單引號包裝查詢。 – bishop 2015-02-23 19:45:20

+1

然後,它似乎是作爲CMD的一部分而出現的字面\ *,而不是根據需要轉義 – atxdba 2015-02-23 19:49:53

+0

@cerebriform:在此情況下,沒有引用變化可以提供幫助。問題是你不能在另一個字符串中嵌入(轉義的)帶引號的字符串,並且使用簡單的變量擴展('$ CMD')將嵌入的字符串識別爲這樣;看到我的答案更多。 – mklement0 2015-02-23 21:19:21

回答

4

你可以使用:

qry='select * from db' 
mysql -e "$qry" 

這不會受到*擴張的外殼。

如果你想存儲mysql命令行也然後使用BASH陣列:

cmd=(mysql -e "$qry") 
"${cmd[@]}" 
1

注:anubhava's answer有合適的解決方案。
此答案提供背景信息。

至於爲什麼你的方法沒有奏效:

"$CMD"不起作用,因爲bash中看到整個價值爲令牌,它解釋爲命令名稱,這顯然會失敗。


`$CMD` 

即,在反引號包圍$CMD,是沒有意義的在這種情況下(並且將具有意想不到的副作用,如果命令產生標準輸出輸出[1]);僅使用:

$CMD 

產生相同的 - 只有更有效的結果( - - 斷通過在反引號包圍,則不必要地創建子外殼;使用反引號 - 或,更好,$(...)另一個嵌入一個命令僅當 - 見command substitution)。


$CMD不起作用,

  • 因爲不帶引號的使用*科目它路徑擴展(通配符) - 其他shell擴展中。
  • \ - 轉義glob字符。在字符串中導致\保留當字符串執行時。

雖然它可能似乎,你已經通過將其放置(間接)之間的雙引號字符串內的轉義雙引號(\"$QRY\")雙引號括起來的*,在外殼程序查看這些轉義雙引號之間的單引號字符串

相反,這些雙引號成爲字面份令牌它們鄰接的,並且殼仍然執行字分裂(解析成由空格分開的參數)上的字符串,和擴展諸如通配符上所得到的標記。

如果我們假設爲通配符被關閉(通過set -f)了一下,這裏是傳遞給mysql參數的故障時,殼求值(不帶引號)$CMD

  • -e # $1 - 所有剩餘的參數是無意間拆分的SQL命令。
  • "select # $2 - 注意"已成爲爭論
  • * # $3
  • from # $4
  • mysql" # $5的文本部分 - 注意,"已經成爲爭論的文本部分

的只有使用才能讓您的解決方案與現有的單個字符串變量一起工作如下:

eval "$CMD" 

這樣,嵌入式逃脫雙引號字符串被正確解析爲單,雙引號字符串(到沒有被施加通配),其中(後引用刪除)的傳遞一個參數爲mysql

然而,eval通常是要避免由於它的安全隱患(如果你不(完全)控制字符串的內容,任意的命令可以執行)。

同樣,請參閱anubhava's answer以獲得正確的解決方案。


[1]的說明重新使用`$CMD`如通過本身的命令:
它可使bash從$CMD執行標準輸出輸出作爲另一命令,這是很少的意圖,並且一般將導致命令中斷,或者更糟糕的是,命令帶來意想不到的效果。
嘗試運行`echo ha`反引號 - 與$(echo ha)相同);你會得到-bash: ha: command not found,因爲bash試圖執行命令的輸出 - ha - 作爲命令失敗。

+0

eval比反引號更安全嗎? – atxdba 2015-02-24 05:28:47

+0

@atxdba:是的,因爲eval允許將命令注入到僅僅是可變擴展不會執行的字符串中。考慮'v ='日期;回聲注入命令'。 '$ v'會失敗(它將所有的標記作爲_single_命令處理),而'eval「$ v」'會將字符串解析爲命令行並執行注入的命令。如果你完全控制你傳遞給它的字符串的創建,使用'eval'是可以接受的,但是使用'eval'是一個危險的習慣。在大多數情況下,當然在這種情況下,存在安全的替代方案。 – mklement0 2015-02-24 15:47:40