使用從 args 讀取的命令和「未終止的引號字串」/「意外的 EOF」從 sh (dash) 呼叫 bash

使用從 args 讀取的命令和「未終止的引號字串」/「意外的 EOF」從 sh (dash) 呼叫 bash

只是想我會記錄一下:我正在嘗試一些非常簡單的事情 - 在 中設置 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-ca=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;"'

由於您不想在bashsh任一方呼叫時展開任何內容,因此也可以在其中使用單引號。您不能在單引號字串中放入單引號,但有一種方法可以模擬這種情況: 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

……看起來,只要第一個單引號沒有轉義,並且美元也被轉義 - 它就有效,無論最後的單引號是否被轉義!這仍然讓我很困惑......

相關內容