從腳本中傳遞包含空格的字元串作為命令行參數
我在 mac 上使用 bash shell。
我想寫一個shell腳本’gac’這樣執行
> gac one two three
產生與執行完全相同的效果
> git add . > git commit -m "one two three"
到目前為止,我的腳本是這樣的:
function gac() { git add . concatenated="'$*'" git commit -m "$concatenated" }
我在這裡找到了將 shell 參數連接成一個以空格分隔的字元串(腳本的第二行)的技巧。上面的腳本幾乎可以工作,除了日誌消息讀取
a382806 'one two three'
當我使用我的 shell 腳本時,而不是
a382806 one two three
就像我手動輸入一樣
> git commit -m "one two three"
在命令行上。
有任何想法嗎?
當您在擴展(例如參數擴展)周圍放置雙引號時,擴展的文本不受分詞的影響。(這是在擴展周圍使用雙引號的原因之一;另一個是為了防止萬用字元。)此外,在雙引號內,單引號沒有被特殊處理,因此它們不執行引用,也不會被刪除。
$*``$
因此,正如Michael Homer 所說,您可以省略虛假
'
'
標記,您的功能應該可以工作。我建議這樣寫:gac() { git add . git commit -m "$*" }
您可以使用
function
關鍵字在 Bash 中定義函式,但上面顯示的語法同樣適用,並且可以跨 Bourne 樣式的 shell 移植。為了更直接地解決這裡的概念問題,原始程式碼中的這一行表明您希望擴展其值包含空格的參數,以便您可以將其作為單個參數傳遞給
git
:concatenated="'$*'"
當你自己編寫一個包含空格的參數時,你引用空格,通常在整個字元串周圍加上引號。
'
'
該行中的存在"
"
告訴我您試圖包含您通常會鍵入的引號。該方法不起作用的原因是外殼本身就是解釋您的引號的原因。它們通常對您從 shell 執行的命令沒有任何意義。假設您有以下命令:
some-command 'foo bar' baz
該命令實際上並未將任何引號傳遞給該
some-command
命令。相反,它作為參數1 和參數 2 執行some-command
。(還有一個參數 0,它告訴程序它是如何執行的;shell 會為此傳遞。)foo bar``baz``some-command
使用引號可以告訴 shell參數在哪裡開始和結束。空格通常會告訴 shell 將每一側的文本視為單獨的參數1,但是您想抑制空格對 shell 的特殊含義,這就是 quoting 所做的。當引號被引用時,就像 inner
'
'
inside一樣"
"
,這也消除了它們的特殊含義。然後它們不執行引用,而是按字面意思傳遞給您的命令,git
如其日誌所示:a382806 'one two three'
1 在 shell 的操作中,空格和製表符以兩種相關但不同的方式將文本分成單獨的單詞。首先,當最初解析命令時,不帶引號的空格和製表符分隔詞法標記。其他元字元也這樣做,但它們有額外的效果——例如,
;
將一行分成多個命令。其次,如果在未引用的上下文中執行參數擴展或任何其他由2表示的shell 擴展,則結果會立即進行分詞,分詞使用 in作為分隔符。預設值為$
$IFS
IFS
是一個空格,後跟一個製表符,後跟一個換行符。2或命令替換,即使使用
語法而不是
$(
)
語法。