Bash

使用命令替換的賦值中的嵌套雙引號

  • March 24, 2021

投票數 > 3.5K的 StackOverflow答案DIR具有這種用於分配給目前 bash 腳本目錄的單行符:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

我對嵌套的雙引號感到困惑。據我所知,以下片段是雙引號的:

"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"

=…以及(ie $( dirnameand )右側的所有其他)內容均未引用。換句話說,我假設第 2、第 4 和第 6 個"字元分別“關閉”第 1、第 3 和第 5 個"字元。

我了解雙引號的作用"${BASH_SOURCE[0]}",但是另外兩對雙引號的目的是什麼?

另一方面(儘管投票得分很高),上面的程式碼片段不正確,那麼實現其名義意圖的正確方法是什麼?

名義上pwd的意思是:將第一次cd-ing返回的值收集到返回的目錄中dirname "${BASH_SOURCE[0]}",並cd在子shell中執行-ing,以使$PWD父shell的 保持不變)。

關於如何bash(以及一般的外殼)解析輸入,您的困惑是不正確的。在:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

首先,bash將賦值的右側解析為一個長字元串$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ),因為雙引號可以出現在雙引號內。

之後,bash開始解析命令替換。因為從左括號到右括號的所有字元都用於在命令替換中構造命令,所以您將得到:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

shell 繼續解析該複合命令,將其分為兩部分:

  • cd "$( dirname "${BASH_SOURCE[0]}" )"
  • 密碼

然後對 應用相同的解析規則cd "$( dirname "${BASH_SOURCE[0]}" )",但這一次,雙引號不是多餘的,而是有意義的。它們防止 的結果的欄位拆分$( dirname "${BASH_SOURCE[0]}" ),以及${BASH_SOURCE[0]}(與最外面的雙引號相比,在變數賦值的 RHS 中不需要防止split+glob)的擴展。


此規則適用於所有 POSIX shell 中的命令替換。您可以在POSIX 規範的 Token Recognition 部分閱讀更多詳細資訊。

一旦進入內部$(...),報價將從頭開始。

換句話說,"..."並且$(...)可以相互嵌套。命令替換 ,$(...)可以包含一個或多個完整的雙引號字元串。此外,雙引號字元串可能包含一個或多個完整的命令替換。 但是,它們不會交錯。 因此,在命令替換內部開始的雙引號字元串永遠不會擴展到它之外,反之亦然。

所以,考慮:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

內部$(...)是:

dirname "${BASH_SOURCE[0]}"

上面${BASH_SOURCE[0]}是雙引號。$(...)在確定${BASH_SOURCE[0]}是雙引號時,任何外部的雙引號或單引號都無關緊要。

外部$(...)包含:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

在這裡,表達式$( dirname "${BASH_SOURCE[0]}" )是雙引號的。在考慮其中的內容時,在外部外部有引號的事實$(...)是無關緊要的。內部有引號的事實$(...)也無關緊要。

以下是雙引號的匹配方式:

在此處輸入圖像描述

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