%20%E5%91%BC%E5%8F%AB%20bash.png)
只是想我會記錄一下:我正在嘗試一些非常簡單的事情 - 在 中設置 env 變量bash
,然後將其打印出來:
$ bash -c "a=1; echo a$a;"
a
$ bash -c "a=1; echo a\$a;"
a1
現在我想要同樣的東西,但被稱為sh
(在我的系統上,ls -la $(which sh)
給出/bin/sh -> dash
)的參數:
$ sh -c "bash -c "a=1; echo a\$a;""
a$a
# obviously I have to escape inner quotes:
$ sh -c "bash -c \"a=1; echo a\$a;\""
a
# escape the dollar once more?
$ sh -c "bash -c \"a=1; echo a\\$a\" "
sh: Syntax error: Unterminated quoted string
# nope... inner single quotes, then?
$ sh -c "bash -c 'a=1; echo a$a;'"
a
# nope... escape the single quotes?
$ sh -c "bash -c \'a=1; echo a$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found
# nope... escape the dollar too?
$ sh -c "bash -c \'a=1; echo a\$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found
所以,我的問題是 - 轉義的正確語法是什麼,這樣sh -c [bash -c ...]
可以得到與剛才相同的結果bash -c ...
?
答案1
單引號內,沒有字元具有特殊意義。雙引號內,"\$`
有特殊意義。從外向內計算:首先弄清楚外殼是由什麼弦組成的,然後是內殼將由它組成。
例如,假設變數a
沒有在外殼中定義,則
sh -c "bash -c \"a=1; echo a\$a;\""
外殼看到一個雙引號字串,它擴展為bash -c "a=1; echo a$a;"
,並且該字串被傳遞給中間sh
。將其解析為使用兩個參數和sh
的調用,後者是由於擴展未定義變數的雙引號字串而產生的。bash
-c
a=1; echo a;
"a=1; echo a$a;"
a
如果您進行此分析,您會發現獲得您想要的東西的一種方法是"a=1; echo a\$a;"
在這個階段獲得。為了獲得這個額外的反斜杠,您需要在原始檔案中添加兩個反斜杠,因為雙引號內已經有一個 shell 擴展階段。二加一等於三。
sh -c "bash -c \"a=1; echo a\\\$a;\""
對外部字串使用單引號會更簡單,因為您不想擴展其中的任何內容。
sh -c 'bash -c "a=1; echo a\$a;"'
由於您不想在bash
從sh
任一方呼叫時展開任何內容,因此也可以在其中使用單引號。您不能在單引號字串中放入單引號,但有一種方法可以模擬這種情況: put '\''
。形式上,這會終止單引號文字,附加一個單引號文字,並開始一個新的單引號文字,但您可以將四個字元序列'\''
視為將單引號放入單引號字串中的一種方法。
sh -c 'bash -c '\''a=1; echo a$a;'\'''
你可以''
在最後省略它,它不太系統,但更容易看到。
sh -c 'bash -c '\''a=1; echo a$a;'\'
單引號在雙引號內並不特殊,因此在編寫時需要在美元前面加上反斜杠,以防止在外殼中"bash -c 'a=1; echo a\$a;'"
擴展。$a
答案2
好吧,我找到了一些可以工作的(注意,這是 Ubuntu 11.04):
$ sh -c "bash -c 'a=1; echo a\$a \'"
a1
$ sh -c "bash -c 'a=1; echo a\$a;'"
a1
……看起來,只要第一個單引號沒有轉義,並且美元也被轉義 - 它就有效,無論最後的單引號是否被轉義!這仍然讓我很困惑......