web-dev-qa-db-ja.com

投票数の多いワンライナーでの二重引用符のネスト

StackOverflow answer 3.5Kを超える投票では、現在のbashスクリプトのディレクトリをDIRに割り当てるためのこの1行が特徴です。

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

ネストされた二重引用符に戸惑っています。私の知る限り、次のフラグメントは二重引用符で囲まれています。

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

...および=の右側にあるその他すべて(つまり、$( dirnameおよび))は引用符で囲まれていません。つまり、2番目、4番目、6番目の"文字は、それぞれ1番目、3番目、5番目の"文字を「閉じる」と想定しています。

"${BASH_SOURCE[0]}"の二重引用符が何を実現するか理解しましたが、他の2組の二重引用符の目的は何ですか?

一方、上記のスニペットが正しくない(そして高い投票スコアにかかわらず)場合、その名目的を達成するための正しい方法は何ですか?

((公称意図によって):つまり、最初にpwd- ingを実行した後、cdによって返された値を、返されたディレクトリに収集しますdirname "${BASH_SOURCE[0]}"によって、サブシェルでcd- ingを実行して、親シェルの$PWDが変更されないようにします)。

22
kjo

あなたのパズルは、bash(および一般的にシェル)が入力をどのように解析したかについて正しくありません。に:

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

最初に、bashは、1つの長い文字列$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )への代入の右側を解析します。二重引用符は、 double quotes の内部に表示できるためです。

その後、bashはコマンド置換の解析を開始します。開き括弧から囲み括弧までのすべての文字は、コマンド置換内のコマンドの作成に使用されるため、次のようになります。

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

シェルは引き続きその複合コマンドの解析を行い、2つの部分に分割します。

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

次に、同じ解析ルールをcd "$( dirname "${BASH_SOURCE[0]}" )"に適用しますが、今回は二重引用符は冗長ではありませんが、意味があります。これらは、$( dirname "${BASH_SOURCE[0]}" )の結果のフィールド分割、および_${BASH_SOURCE[0]}_の展開を防ぎます(最も外側の二重引用符とは対照的に、 はRHSでは必要ありません) _split+glob_ )を防ぐための変数割り当ての例。


このルールは、すべてのPOSIXシェルの コマンド置換 に適用されます。より詳細なパズルは、POSIX仕様の Token Recognitionセクションで読むことができます

13
cuonglm

$(...)の中に入ると、引用は最初からやり直しになります。

言い換えると、_"..."_と$(...)は、相互にnestできます。プロセス置換$(...)には、1つ以上のcomplete二重引用符付き文字列を含めることができます。また、二重引用符で囲まれた文字列には、1つ以上のcompleteプロセス置換が含まれる場合があります。 しかし、それらはインターレースしません。したがって、プロセス置換の内部で始まる二重引用符で囲まれた文字列は、外部に拡張されることはありません。

だから、考慮してください:

_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]}" )が二重引用符で囲まれています。外側の$(...)の外側に引用符があるという事実は、その内側に何があるかを考えると無関係です。内部の$(...)内に引用符があることも関係ありません。

二重引用符が一致する方法を次に示します。

enter image description here

23
John1024