it-swarm-ja.com

コマンド置換でエスケープされていないBash引用符

誰かがこれが機能している理由を説明できますか(名前に空白が含まれているディレクトリの内容を一覧表示します):

ret="$(ls "my dir")"

それはむしろ次のように解釈されるべきではありません:

ret="$(ls "
my dir
")"

たとえば、次のようになります。

ls "my" "dir"

そして

ls "my dir"
3
user2279268

これまでのところ最良の推測は、あなたが尋ねていることのようです:

コマンド

    ret = "$(ls" my dir ")"

は、4つの二重引用符(_"_)マークを含むコマンドのかなりひどい例です。次のように、2番目の見積もりが最初の見積もりと一致し、4番目の見積もりが3番目の見積もりと一致することを素朴に期待するかもしれません。

_    ret="$(ls "my dir")"
        ↑-----↑      ↑-↑
_

たとえば、

_    eat "afternoon snack" dinner "midnight snack"
_

代わりに、次のように「機能」します。

    ret = "$(ls" my dir ")" 
↑↑------↑↑
↑--------------↑

ネストされた引用符がそのように解析されるのはなぜですか?

bash(1) のこの段落はそれを説明するかもしれません:

コマンド置換


    $(command) formを使用する場合、括弧内のすべての文字がコマンドを構成します…。

これは、あなたが観察したことを意味していると思います。つまり、_$(_と_)_の間のテキストは、構文要素とは無関係に、独自の引用符の解析/ペアリングを使用して、別個のコマンドであるかのように扱われます。括弧の外。その意味を探さなければ、解釈するのは非常に難しいと私は認めます。


しかし、書かれているように、あなたの質問は意味がありません。全体は、シェルに対する_$_の非常に特別な意味にかかっています。それを他の通貨記号に変更した場合、

_    ret="£(ls "my dir")"
_

その場合、2つの単語として扱われます。

_ret="£(ls "my_
(に続く)
_dir")"_

なぜなら、空白でも特殊文字でもない文字が、開始引用符の直前または終了引用符の直後に表示される場合、引用符で囲まれた文字と同じ文字列に含まれるためです。例えば、

_    cat Wal"*"mart
_

Walというファイルではなく、_Wal*mart_というファイル、_*_というファイル、martというファイルを探します— _Wal"*"mart_は_Wal\*mart_および_"Wal*mart"_。同様に、次の例は4つの単語を示しています。

    1つ "" 2つのバックル "私の"靴/ don\'t/be/a/""/cated sqrt "(2)" 
↑-------↑↑------ --------↑↑--------------------↑↑-------↑

質問で示した3行の内訳をどこで取得したのかわかりません。