Bash

單引號和雙引號是由“bash”還是由“echo”處理的?

  • December 24, 2017

當你做這樣的事情時:

echo 'Hello World'

或者像這樣:

x=12345
echo "x is: $x"

在第一個範例中,echo命令是接收'Hello World'還是接收Hello World

在第二個範例中,echo命令是接收"x is: $x"還是接收x is: 12345

所以基本上我的問題是:單引號和雙引號是由bash還是由處理的echo

引號、變數擴展、萬用字元以及bash 手冊中有關擴展的部分中提到的所有其他內容都由 bash 處理。

例如,當您執行 bash command 時echo "x is: $x",bash 對其進行解析以發現它需要執行echo帶有一個參數的命令,即x is: 12345. 給定echo "x is" "$x", bashecho使用兩個參數執行:x is12345— 這就是為什麼保留引號內的兩個空格(它們是未修改的 echo 列印的參數的一部分),但引號外的兩個空格不是(對於 shell,兩個分隔參數的空格與單個參數一樣好,並且echo始終在其間列印一個空格)。

命令(echo或任何其他命令)無法知道哪個 shell 命令產生了參數x is: 12345,或者實際上是否涉及 shell。以下是一些產生此參數的範例命令:

echo "x is: 12345"
echo 'x is: 12345'
echo x\ is:\ 12345
echo "x is: $x"
echo 'x is:'\ "$x"
echo "$(echo "x ")is: $x"
# Assume there is no other file whose name begins with x in the current directory
touch "x is: $x"; echo x*

或者它可以exec "echo", "x is: 12345"在 Perl 或execlp("echo", "echo", "x is: 12345")C 等中。

這適用於每個命令。同樣的原則也適用於其他 shell,儘管它們每個都有稍微(或顯著)不同的擴展集。

另一方面,選項由命令處理。例如,ls -l -tls -l "-t"bash(或任何類似的 shell)中,兩者都ls以完全相同的方式執行,帶有兩個參數-l-t. 這就是為什麼如果您想執行ls以顯示有關名為-t. 您可以使用 來做到這一點ls -l -- -t,即--作為參數傳遞。這是大多數命令遵循的約定:後面的任何內容都不會--被解析為選項。再一次,這是命令的一個特性;對於 shell,前導破折號沒什麼特別的。

可能會變得棘手的一件事是反斜杠。在 bash 和其他 shell 中,任何引號之外的反斜杠意味著下一個字元失去其特殊含義。例如,echo \"x\ is:\ 12345\"prints "x is: 12345",因為前面有反斜杠的每個字元都失去了它們的特殊含義(引號語法"用於空格,單詞分隔符用於空格)。但有些命令也解釋反斜杠。當他們這樣做時,您需要確保反斜杠到達他們。例如,在 bash 中,該echo命令預設按字面意思列印反斜杠,但如果您傳遞選項-eshopt xpg_echo先執行,則echo有其自己的轉義序列(這是針對 bash,echo不同 shell 和不同系統中的命令對於是否特殊處理反斜杠有不同的規則)。例如,echo 'a\nb'prints a\nbwhile echo -e 'a\nb'prints a-newline-b因為\n意味著“換行符”到echo -e. 另一方面,echo a\nbprintssince被 shell 擴展,意思anb是“引用下一個字元”。\n``\

此外,當涉及多個 shell 時要小心,例如使用 SSH。在 shell 中執行ssh時,本地 shell 會像往常一樣解析命令。SSH 客戶端用空格連接它的非選項參數,並將結果字元串發送到 SSH 伺服器。SSH 伺服器將此字元串傳遞給遠端 shell。這意味著在您在終端或 shell 腳本中鍵入的內容與在遠端機器上執行的內容之間存在兩輪完整的 shell 擴展。

引用自:https://unix.stackexchange.com/questions/412823