シングルクォートを使用すると、grep が期待どおりの結果を返さないのはなぜですか?

シングルクォートを使用すると、grep が期待どおりの結果を返さないのはなぜですか?

以下の内容のファイルがあります:

sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!

上記のファイルで「-example」を検索しているときに、grep コマンドは目的の出力を返しません。パターンに「-」が含まれている場合は、-e オプションを使用する必要があることはわかっています。

最初の例では-例引用符なしで直接:

sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example

-例一重引用符付き:

sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example

-例二重引用符とエスケープ文字を含む

sh-4.2$ grep "\-example" file1
-example
sh-4.2$

答え1

さて、検索パターンに '-' が含まれていることはご存知でしょうし、検索パターンに '-' が含まれている場合はフラグを使用する必要があることもご存じでしょう-e。フラグを使用していないため、-eシェルは代わりに「パターン」を引数 (およびパラメータ) として解釈します。次のコードでそれを確認できます。

$ grep "-foo" file1
grep: oo: No such file or directory

さらに、コードは、引数とパラメータ「xample」を使用してgrep "-example" file1実行することをシェルに伝えます。grep-e

これは、 のようなことをしようとしたときに発生するのと同じ問題です。これrm -my-silly-file-nameは機能しないので、rm ./-my-silly-file-name代わりに のようなものを使用する必要があります。別の回避策は ですrm -- -my-silly-file-name。この慣用句をここで使用できます。

$ grep -- "-example" < file1
-example

「--」は、シェルにその後のすべてがない引数。

あるいは、ご覧のように、単に「\」で「-」をエスケープすることもできます。

grep "\-example" file1

この記事では引用について詳しく説明します: 該当部分はシェルによって解釈されるパラメータとバッククォートされたコマンドは、二重引用符で囲まれます。二重引用符を使用すると、内容はシェルによって解釈されます。

答え2

「パターンが [-] で始まる場合は -e オプションを使用する必要がある」ことはわかっていますが、必要なときに使用していません。grep -e -example file1期待どおりの結果が得られます。

各例で実際に実行される内容は次のとおりです。

  • grep -example file1=> grep -e xample file1(-e が必要です)
  • grep '-example' file1=> grep -e xample file1(-e が必要です)
  • grep "\-example" file1=> grep \-example file1(-e は必要ありません)

答え3

で始まる引数は-オプションとして扱われます。

最初の 2 つのケースでは、 に渡される最初の引数grepは であり-example、これは(オプションへの引数なので を検索します)grepとして理解されます。-e xamplexample-example

3 番目のケースでは、\-exampleが に渡されますgrep。 で始まっていないため-、オプションとして扱われません。代わりに、正規表現として扱われます。ただし、 の動作は\-POSIX に従って指定されていないため、何に一致するかについては保証されません。ほとんどのgrep実装では、\-は に一致しますが、 が特殊演算子である可能性がある実装-を想像できます(たとえば、 は特殊演算子であり、リテラル には一致しないGNU whereを参照してください)。grep\-grep\++

-exampleオプションとして扱われないようにするには、次のいずれかが必要です。

  • grep -- -example file. は--オプションの終わりを示します。それ以降のものはオプションではありません (つまり、最初の引数は検索するパターンで、残りは検索するファイルのリストです)。
  • grep -e -example fileここで、はオプション-exampleの引数として扱われます-e

これが、書くことに慣れるべき理由です。

grep -e "$pattern" file

または

grep -- "$pattern" file

保証できない場合は$patternで始まりません-

ここで、次のように書くこともできることに注意してください。

grep '[-]example' file

見てもbash で予期しない文字に一致する括弧式 (範囲なし)そのアプローチで起こり得る合併症について。

関連情報