Bashで二重引用符を一致させる方法は?

Bashで二重引用符を一致させる方法は?

を使用していますGNU bash 4.3.48。ドル記号だけが異なる次の2つのコマンドを検討してください。

コマンド1:

echo "(echo " * ")"

コマンド2:

echo "$(echo " * ")"

彼らの出力は

(echo  test.txt ppcg.sh )

そして

 * 

明らかに、最初のケースでは*ワイルドカードが使用されます。つまり、最初の引用文は2番目の引用文とペアになり、3番目と4番目の引用文は別のペアを形成します。

2番目のケースには*ワイルドカードがなく、出力に正確に2つの追加スペース(アスタリスクの前後に1つずつ)があります。これは、2番目の引用符が3番目の引用符で使用されることを意味します。最初の引用符は次のとおりです。 4番目の引用符で使用されます。

$()引用符が次の引用符と一致しませんが、入れ子になっている構造に他のケースはありますか?この動作はよく文書化されていますか?では、その文書はどこにありますか?

答え1

文字列内に挿入できるすべての入れ子構造は、その中に追加の文字列を含めることができます。閉じるタグまで、新しいスクリプトのように解析され、複数のレベルの深さにネストすることもできます。そのうちの1つだけを除いて、すべてで始まります$。これらはすべて、BashマニュアルとPOSIXシェルコマンド言語仕様の組み合わせで文書化されています。

これらの構造にはいくつかのケースがあります。

  • コマンドは次のように置き換えられます。$( ... )、発見したように。POSIXはこの動作を指定します:

    この$(command)形式では、左角かっこの後から一致する右角かっこまでのすべての文字がコマンドを構成します。有効なシェルスクリプトは何でも使用できます。注文する...

    引用符は有効なシェルスクリプトの一部であるため、一般的な意味が許可されます。

  • また、コマンド置換を使用してください`
  • 「単語」要素次の高度なパラメータの代替例${parameter:-word}。これ「単語」の定義は次のとおりです。:

    シェルで1つの単位として扱われる一連の文字

    - これには、引用されたテキストと混在した引用文も含まれますa"b"c'd'e。しかし、拡張プログラムの実際の動作はこれより少し自由です${x:-hello world}

  • 算術拡張with $(( ... ))、デフォルトでは役に立たないが、コマンド置換や変数拡張を入れ子にしてから、その中に便利な引用符を使うこともできます。POSIXステータス:

    式は二重引用符で囲まれたように処理する必要がありますが、式内の二重引用符は特に処理されません。シェルは、パラメータ拡張、コマンド置換、および引用符の削除のために式内のすべてのトークンを拡張する必要があります。

    だから、このような行動は明らかに必要です。これはecho "abc $((4 "*" 5))"、ワイルドカードではなく算術演算を実行することを意味します。

    以前のスタイルの$[ ... ]算術拡張は次のとおりです。いいえ同じ方法で処理されます。拡張子が引用されているかどうかにかかわらず、引用符があるとエラーが発生します。このフォームには記録がなくなり、とにかく使用できません。

  • ロケール別翻訳$"..."、実際には"コア要素として使用します。$"一つの単位とみなされます。

引用符を含まないネストの場合もあります。支柱の拡張{a,b{c,d},e}「a bc bd e」に展開されます。${x:-a{b,c}d}するいいえa{b,cただし、Nestでは、 ""の後ろに""が続くパラメータは一般的に扱われますd}。それ記録もある:

中括弧を使用するときに一致する閉じ括弧は、バックスラッシュでエスケープされていないか、引用符付き文字列内にあり、埋め込み算術拡張、コマンド置換、または引数拡張内にない最初の「}」です。


通常、すべての区切られた構文は周囲のコンテキストとは無関係にその本体を解決します。例外はエラーとして扱われます。)。基本的に、$(コマンド置換コードは、パーサーに本文から取得できる内容を使用して新しいプログラムのように動作するように要求し、サブパーサーが実行されたときに予想される終了トークン(エスケープされていない、または)))が表示されることを}確認します。摂取できるもの。

考えているなら再帰下降パーサー、これは基本的なケースの単純な再帰です。文字列補間を実行すると、実際には他の方法よりも簡単になります。これらの構成をサポートするシェルは、基本的な解析技術に関係なく同じ結果を提供します。

これらの構造により、任意に深い場所に参照を入れ子にすることができ、期待どおりに機能します。真ん中にある引用文を見て混同する人はいないでしょう。代わりに、これは内部コンテキストで引用された新しい文字列の始まりです。

答え2

printfおそらく(代わりに)この2つの例を見てみるとecho便利です。

$ printf '<%s> ' "(echo " * ")"; echo
<(echo > <test.txt> <ppcg.sh> <file1> <file2> <file3> <)>

(echo (末尾のスペースを含む最初の単語)、いくつかのファイル、および末尾の単語を印刷します)
角かっこは単に文字列の一部を引用します(echo 
アスタリスク(2つの二重引用符がペアになっているため、引用符はありません)はファイルリストと一致するグローバル変数に展開されます。
それには閉じ括弧があります。

ただし、2番目のコマンドは次のように動作します。

$ printf '<%s> ' "$(echo " * ")" ; echo
< * >

$コマンドの置換を開始します。引用が再開されます。
アスタリスクは引用符で囲まれており、" * "これがコマンド(ここでは引用符付きの文字列ではなくコマンド)が出力するものechoです。最後にprintf再フォーマット*してください< * >

関連情報