web-dev-qa-db-ja.com

正規表現では、どの文字をエスケープする必要がありますか?

一般的に、正規表現のどの文字をエスケープする必要がありますか?

たとえば、次の構文は正しくありません。

echo '[]' | grep '[]'
grep: Unmatched [ or [^

ただし、これは構文的には正しいisです。

echo '[]' | grep '\[]'
[]

正規表現でエスケープする必要がある文字とエスケープしてはならない文字に関するドキュメントはありますか?

25
LanceBaynes

これはアプリケーションによって異なります。あなたの例では[は、grepの引数として引用符で囲む必要がありますが、echoは引用符で囲まないでください。

シェルの場合( POSIX仕様 から):

引用は、シェルに対して特定の文字または単語の特別な意味を取り除くために使用されます。引用を使用して、次の段落の特殊文字の文字どおりの意味を維持し、予約語がそのように認識されないようにし、ヒアドキュメント処理内でのパラメータ展開とコマンド置換を防止できます(ヒアドキュメントを参照)。

アプリケーションは、次の文字を表す場合、それらを引用する必要があります。

|  &  ;  <  >  (  )  $  `  \  "  '  <space>  <tab>  <newline>

また、特定の状況下では、以下を引用する必要がある場合があります。つまり、これらの文字は、IEEE Std 1003.1-2001のこのボリュームの他の場所で説明されている条件に応じて特殊になる場合があります。

*   ?   [   #   ˜   =   %

さまざまな引用メカニズムは、エスケープ文字、単一引用符、および二重引用符です。ヒアドキュメントは別の形の引用を表しています。ヒアドキュメントを参照してください。

特定のプログラム(正規表現、Perl、awkを使用)には、エスケープに関する追加の要件があります。

14
Matteo

正規表現には複数のタイプがあり、特殊文字のセットは特定のタイプに依存します。それらのいくつかを以下に説明します。すべての場合において、特殊文字はバックスラッシュ_\_によってエスケープされます。例えば。 _[_に一致させるには、代わりに_\[_と記述します。あるいは、文字(_^_を除く)は、_[[]_のように1つずつ角括弧で囲んでエスケープすることもできます。

(サブ)式の先頭にある_^_ specialなどの一部のコンテキストで特殊な文字は、すべてのコンテキストでエスケープできます。

他の人が書いたように:シェルで式を単一引用符で囲まない場合、すでにエスケープされた正規表現でシェルの特殊文字をさらにエスケープする必要があります。例:_'\['_の代わりに、bashのようなBourne互換シェルで_\\[_(または_"\["_または_"\\["_)と書くことができますが、これは別の話です。

基本正規表現(BRE)

  • POSIX:基本正規表現
  • コマンド:grepsed
  • 特殊文字:_.[\_
  • 一部のコンテキストでは特別:_*^$_
  • 文字列をエスケープする:"$(printf '%s' "$string" | sed 's/[.[\*^$]/\\&/g')"

拡張正規表現(ERE)

  • POSIX:拡張正規表現
  • コマンド:_grep -E_、GNU:_sed -r_、* BSD:_sed -E_
  • 特殊文字:_.[\(_
  • 一部のコンテキストでは特別:_*^$)+?{|_
  • 文字列をエスケープする:"$(printf '%s' "$string" | sed 's/[.[\*^$()+?{|]/\\&/g')"
9
pabouk

各アプリケーションには、独自の「特殊」文字のセットがあります。あなたが遭遇した問題は、シェルではなくgrepにありました。 grepで引用する必要がある文字については、「正規表現」のマンページのセクションを参照してください。

シェルの場合、引用符で囲まれる必要がある文字は次のとおりです。

;'"`#$&*?[]<>{}\

および任意の空白。

シェルによっては、他の文字も引用符で囲む必要がある場合があります。

!^%

シェルのマンページの「Shell GRAMMAR」を見てください。

8
Arcege

grepは、正規表現メソッドとしてBREを使用します。良いドキュメントがあります here 、一般的な概要は、「特殊文字またはメタ文字をエスケープしてそのリテラルを取得し、エスケープしてエスケープシーケンスを作成する(\n\r、etc) "、これは常に正しいとは限りませんが、たとえば、エスケープする必要があります(および)特別な意味(後方参照)を取得します。

3
Chris Down

シェルは、コマンドを実行する前にコマンドラインを変換する場合があります。シェルとgrepの両方で、一部の文字の特別な意味を取り除くために引用符を使用できます。それにもかかわらず、grepとシェルには異なる特殊文字があります。さらに、既存の展開に起因しないエスケープされていない特殊文字は、コマンドの実行前にシェルによって削除されます。

echo '[]' | grep '[]'

シェルは引数[]grepに送信し、grepによって不正なブラケット式として解析されます。

echo '[]' | grep \[]

上で、同様のケースを見ることができます。バックスラッシュが削除され、[]grepへの引数として送信されます。 grepは、誤った形式の角かっこ式を認識します。

echo '[]' | grep '\[]'

最後に、この場合、引用符はシェルによって削除され、\[]grepへの引数として送信されますが、この特定のケースでは、\[grepをリテラルブラケットとして。バックスラッシュがシェルによって特殊文字として解釈されないようにするには、引用符が必要です。


¹ POSIX仕様

0
Fólkvangr