web-dev-qa-db-ja.com

`a [bc] d`(大括弧)と` a {b、c} d`(大括弧)の違いは何ですか?

違いは何ですか a[bc]dおよびa{b,c}d?なぜ人々はa{b,c}dが既に存在する場合a[bc]d

28
Weijun Zhou

2つはかなり異なります。

_a[bc]d_はファイル名パターンです(fish以外のシェルの場合)。現在のディレクトリにある既存のファイルの名前の場合、2つのfilenamesabdacdに展開されます。

  • _[...]_の部分は、リストされた文字(または範囲が含まれている場合は照合要素)から単一の文字に一致する、括弧で囲まれた式です。パターン_a[bc]d_に一致させるには、ファイル名の文字列adの間の文字がbまたはcである必要があります。

  • abdは存在するがacdは存在しない場合は、abdにのみ展開され、その逆も同様です。

  • シェルとオプションによっては、abdacdも存在しない場合、エラーが発生します(元のUnix sh、_(t)csh_、zshfish、_bash -O failglob_)を使用してシェルを終了するか、パターンを展開せずにそのままにするか(Bourne-likeおよびrc- like shells)、または何も展開しない(_bash/zsh/yash -o nullglob_、いくつかの古いバージョンのfish、元のUnix shおよび_(t)csh_(同じコマンドに他の一致するグロブがある場合)。

_a{b,c}d_はブレース展開です(これらをサポートするシェルで)。 2つのstringsabdacdに展開されます。

  • _{...}_の部分は、コンマで区切られた文字列のセットです(この例では、一部のシェルでは、_a..k_や_20..25_などの範囲、または_00..20..2_または_0..20..2%02d_)。展開は、これらの各文字列を隣接する文字列aおよびdと組み合わせて計算されます。これらの文字列は、単一の文字よりも長い場合があり、ブレース展開自体である場合もあります。

  • これらの文字列が既存のファイル名に対応するかどうかに関係なく、展開が行われます。

文字列を作成する場合は、ブレース展開を使用します。ファイル名を一致させる場合は、ファイル名パターンを使用します。


particularこの特定のケースでは、_a[bc]d_が既存のファイルの名前になる可能性があるため、これらのシェルで_rm -f ./*.[ch]_のようなものを使用することは潜在的に危険であり、_rm -f ./*.{c,h}_はそれほど問題ではありません。

43
Kusalananda

_a[bc]d_はpattern-matchingであり、POSIX標準の一部です。 POSIXでは、これは「パターンブラケット式」として導入されています。マニュアルの セクション2.13に記載されています

引用符で囲まれておらず、ブラケット式の外側にある場合、次の3つの文字はパターンの仕様で特別な意味を持ちます。

      疑問符は、どの文字にも一致するパターンです。
    *
      アスタリスクは、複数の文字に一致するパターンで説明されているように、複数の文字に一致するパターンです。
      開き角括弧は、パターン角括弧式を導入します。

セクション2.13.3では、ファイル名の拡張に使用された場合に通常の正規表現で期待される動作とは異なる動作についても触れています(私が強調)

これまでに単一の文字と一致するパターンと複数の文字と一致するパターンで説明されているルールは、ファイル名の展開にパターンマッチング表記が使用される場合に適用される次のルールによって修飾されます。

パス名のスラッシュ文字は、パターンで1つ以上のスラッシュを使用して明示的に照合されます。これは、アスタリスクまたは疑問符の特殊文字、またはブラケット式とは一致しません。パターン内のスラッシュは、ブラケット式の前に識別されるものとします。したがって、ファイル名の展開に使用されるパターンブラケット式にスラッシュを含めることはできません。エスケープされていない開き角括弧文字の後に、対応する閉じ角括弧が見つかる前にスラッシュ文字が見つかった場合、開き角括弧は通常の文字として扱われます。たとえば、パターン_"a[b/c]d"_は、abdや_a/d_などのパス名と一致しません。文字通り_a[b/c]d_のパス名のみに一致します。

_a{b,c}d_は中かっこ展開であり、POSIXの仕様にはありません。これは、bashの対応する部分です manual (私が強調):

ブレース展開は、任意のstringsが生成されるメカニズムです。このメカニズムはfilename Expansion(Filename Expansionを参照)に似ていますが、生成されたファイル名が存在する必要はありません 。ブレース展開されるパターンは、オプションのプリアンブル、の後に一連のコンマ区切りの文字列、または中括弧のペアの間のシーケンス式、その後にオプションのpostscript。プリアンブルは中括弧内に含まれる各文字列の前に付けられ、その後、結果の各文字列にポストスクリプトが追加され、左から右に拡張されます。

@mosvyのコメントによると、これはcshから最初に現れましたが、bashの動作はcshや他のシェルとは異なります。このタイプのブレース展開はglob(3)にもあります。

bash 3.0の後にのみ表示される別のタイプのブレース展開_{a..z}_があり、bash 4.0にはさらに追加されています。

グロビングがオンになっているシェルで、空のフォルダーで実行すると、次の結果が返されます

_$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
_

@Jesse_bのコメントに応じて、対話型シェルを使用していて、両方に当てはまる場合、_a[bc]d_の方が入力の手間が少なくなります。たとえば、_grep pattern [ab][12].txt_です。

7
Weijun Zhou