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


28

違いは何であるa[bc]dとはa{b,c}da{b,c}dすでにあるのに、なぜ人々は使うのa[bc]dですか?


誰が使用するように言ったのですcommand a[bc]dか?
Jesse_b

3
正しく理解すれば、確かに用途があります。
周jun順

7
私は2つの間の混乱がどのように起こったのか理解していないと思います。
Jesse_b

最近ではありませんが、これについてLinuxにあまり詳しくない同僚から明示的に尋ねられました。
ウェイジュン周

@Jesse_bのようなファイルに対する操作でそれらを試してみて、ls単一の文字だけを試してみた場合、それらは同じように見えるでしょう。
Nacht-モニカの復職

回答:


43

この2つはまったく異なります。

a[bc]dあるファイル名のパターン(以外のシェルではfish)。それは2つのに拡大するファイル名 abdacd、それらの場合は、現在のディレクトリ内の既存のファイルの名前があります。

  • この[...]部分は、リストされた文字(または範囲が含まれる場合は照合要素)のうちの1文字に一致する括弧で囲まれた式です。パターンに一致するにはa[bc]d、文字列間の文字ad、ファイル名には、いずれかでなければなりませんbc

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

  • どちらの場合はabd、もacd存在するが、シェルおよびオプションに応じて、それはエラー(オリジナルのUnixの引き金となりsh(t)cshzshfishbash -O failglob)およびおそらくシェルを終了、またはパターンunexpanded¹を残す(ボーン様およびrc様シェル)以上に拡大何もありません(bash/zsh/yash -o nullglobfish元のUnixの一部の古いバージョン、shおよび(t)csh同じコマンドに他の一致するグロブがある場合)。

a{b,c}dあるブレース展開(これらをサポートするシェルで)。2つの文字列 abdとに展開されますacd

  • {...}(;いくつかのシェルで、それはまた、などの範囲であってもよい。この例の一部は、文字列のカンマ区切りのセットであるa..kか、20..25など、またはより高度なもの00..20..2又は0..20..2%02d)、および拡張がフランキングしてこれらの文字列のそれぞれを組み合わせることによって計算されます。文字列ad。これらの文字列は、単一の文字よりも長くなる可能性があり、ブレース展開自体になる可能性もあります。

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

文字列を作成する場合は、中括弧を使用します。ファイル名を一致させる場合は、ファイル名パターンを使用します。


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


「abdが存在するがacdが存在しない場合、abdのみに拡張される」ことを明確にしていただきありがとうございます。それが私の答えに欠けていると思います。
周jun順

9
もう一つの決定的な違いはでていることであるa{b,c}dbc部品の単一文字である必要はありません。例えばex{ten,ci}sion。while ex[tenci]sionまたは何でもこれらの文字の1つにのみ一致します。
アレクシス

7

a[bc]dあるパターンマッチング、および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 マニュアルの対応する部分を次に示します(私による強調)。

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

@mosvyのコメントによると、これは最初に表示されましたcshが、動作bashcsh他のシェルとは異なります。このタイプのブレース拡張もにありglob(3)ます。

3.0の{a..z}後にのみ現れた別のタイプの中括弧の拡張bashがあり、bash4.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


2
ブレースの展開は「バシズム」ではありません。それcshはずっと前に初めて登場しましたbash。また、glob(3)ライブラリ関数にも存在します。違いは、bash他の展開の前に実行されることa=A; ab=A/B; ac=A/C; echo $a{b,c}です。他のシェルとは異なる方法でbashで動作します。
mosvy

ありがとうございました。答えを更新します。
ウェイジュンジュウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.