Bash

bash 中的雙引號如何匹配(配對)?

  • February 5, 2018

我正在使用GNU bash 4.3.48. 考慮以下兩個僅相差一個美元符號的命令。

命令 1:

echo "(echo " * ")"

命令 2:

echo "$(echo " * ")"

它們的輸出分別是

(echo  test.txt ppcg.sh )

* 

所以很明顯在第一種情況下*是全域的,這意味著第一個引號與第二個引號形成一對,第三個和第四個形成另一個對。

在第二種情況下,*不是全域的,並且輸出中正好有兩個額外的空格,一個在星號之前,一個在星號之後,這意味著第二個引號與第三個引號一起出現,而第一個引號與第四個引號一起出現。

$()除了引號不與下一個匹配而是嵌套的構造之外,還有其他情況嗎?這種行為是否有據可查,如果有,我在哪裡可以找到相應的文件?

任何可以在字元串中插入的嵌套結構都可以在其中包含更多的字元串:它們像新腳本一樣被解析,直到結束標記,甚至可以嵌套多層。所有這些都以 . 開頭$。所有這些都記錄在 Bash 手冊和 POSIX shell 命令語言規範的組合中。

這些結構有幾種情況:

使用該$(command)形式,從左括號到匹配的右括號的所有字元構成命令。任何有效的 shell 腳本都可以用於命令

引號是有效 shell 腳本的一部分,因此它們的正常含義是允許的。

被 shell 視為一個單元的字元序列

  • 包括引用的文本甚至混合引號a"b"c'd'e- 儘管擴展的實際行為比這更自由一些,例如${x:-hello world}也有效。
  • 用 進行算術擴展$(( ... ))雖然它在那里基本上沒用(但您也可以嵌套命令替換或變數擴展,然後在其中有用地使用引號)。POSIX 聲明

表達式應被視為在雙引號中,但表達式中的雙引號沒有被特殊處理。shell 應擴展表達式中的所有標記,以進行參數擴展、命令替換和引號刪除。

所以這種行為是明確要求的。這意味著echo "abc $((4 "*" 5))"算術,而不是萬用字元。

請注意,舊式$[ ... ]算術擴展的處理方式不同:如果出現引號,則無論擴展是否被引用,引號都是錯誤的。這個表格根本沒有記錄,無論如何也不打算使用。

還有一種您可能沒想到的嵌套情況,不涉及引號,它帶有大括號擴展{a,b{c,d},e}擴展為“a bc bd e”。但是,不${x:-a{b,c}d}嵌套;它被視為參數替換,給出“ ”,後跟“ ”。這也記錄在案a{b,c``d}

當使用大括號時,匹配的結束大括號是第一個沒有被反斜杠或帶引號的字元串轉義的’}’,並且不在嵌入式算術擴展、命令替換或參數擴展中。


作為一般規則,所有定界構造都獨立於周圍的上下文解析它們的主體(並且異常被視為錯誤)。本質上,在看到命令替換程式碼時,它只是要求解析器從主體中消耗它可以使用的東西,就好像它是一個新程序一樣,然後在子解析器執行時$(檢查預期的終止標記(未轉義的)or )))是否出現}它可以消耗的東西。

如果您考慮遞歸下降解析器的功能,那隻是對基本情況的簡單遞歸。一旦你有了字元串插值,它實際上比其他方式更容易做到。不管底層的解析技術如何,支持這些結構的 shell 都會給出相同的結果。

您可以通過這些結構盡可能深入地嵌套引用,它會按預期工作。看到中間的引用不會讓任何地方感到困惑;相反,這將是內部上下文中新引用字元串的開始。

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