grepの正規表現ではエスケープ文字を引用する必要がありますが、オンライン正規表現エンジンでは引用しないでください。

grepの正規表現ではエスケープ文字を引用する必要がありますが、オンライン正規表現エンジンでは引用しないでください。

私はこの質問のいくつかのバージョンが以前に質問され答えられたと確信していますが、周りを見回しましたが、明確な答えが見つかりませんでした。たぶんここで誰かが電球をつけるのを手伝ってくれるかもしれません。私はMojave 10.14.6とbash 3.2.57(1)リリースがインストールされているMacを使用しています。

オンラインチュートリアルを通じて正規表現の基礎を学び、オンラインウェブサイトで練習しています。https://regexr.comgrep、そして私のローカルコンピュータのbashで使用してください。

私は次の3つを含む小さなテキストファイル(small.txtと呼ばれる)を使って練習しています。

9.00
9-00
9500

.ワイルドカードはその場所のすべての文字と一致することがわかります。したがって、私が使用しているオンライン正規表現エンジン(JavaScript)では、 /9.00/g3つの文字列9.00 9-009500

grepコマンドラインで使用すると、効果は同じです。

~/bin $ grep 9.00 small.txt
9.00
9-00
9500

今まではそんなに良くなった。チュートリアルでは、.メタ文字をリテラルに変換するにはエスケープする必要があると言います。わかりましたので、期待どおりにオンライン正規表現ボックスに入れると、9-00または9500のみが/9\.00/g一致します。9.00ギイ。

ただし、コマンドラインに同じ構文を入力すると、grep予期しない結果が表示されます。

~/bin $ grep 9\.00 small.txt
9.00
9-00
9500

以前と同じです。機能させるには、grep文字列全体を二重引用符で囲む必要があります。

~/bin $ grep "9\.00" small.txt
9.00

または、二重引用符エスケープ文字を使用するだけです。

~/bin $ grep 9"\."00 small.txt
9.00

正しい結果を提供する別の引用を選択することもできます。

このため、正規表現の基本を理解することは困難です。なぜなら、最初にgrepシェルでこれを行う方法を理解する必要があるからです。その他伝統的な正規表現の構文から。正規表現のすべての規則を学ぶだけでは十分に困難ですが、古典的な正規表現とbashシェルの動作の違いを追加すると、頭がぽんと鳴るようです。

とにかく、この問題を解決し、コマンドラインでgrepで使用できる正規表現を正しく学ぶのに役立つ明確な説明があるかどうか疑問に思います。

(正規表現のプロセスのどれもgrepとbashのコマンドラインバージョンとオンライン正規表現テスターで見られる「純粋な」正規表現構文の違いを指摘していません。) 。とても基本的な内容なのに何か抜けたような感じがします。

ありがとうございます。

ベストアンサー1

なぜ?これは、シェルが\例に示したような特殊文字を解釈するためです。

シェルを介して grep の引数として渡す文字列を保護しないため、問題が発生します。

さまざまなソリューション:

  • 一重引用符文字列、
  • 二重引用符で囲まれた文字列(二重引用符を使用すると、シェルは$variables結果文字列をコマンドに送信する前に何かを解釈します)、
  • または、引用符を使用せず(強くお勧めします)、バックスラッシュを正しい場所に追加して、シェルがコマンドに送信する前に次の文字を解釈しないようにしてください。

ほとんどすべてを保存するので、一重引用符で文字列を保護することをお勧めします。

grep '9\.0' #send those 4 characters to grep in a single argument

シェルは一重引用符で囲まれた文字列を文字通り渡します。

注:一重引用符で囲まれたシェル文字列に含めることができない唯一のものは一重引用符です(これは一重引用符が終了するためです)。一重引用符で囲まれたシェル文字列に一重引用符を含めるには、まず一重引用符を終了し、直ちにエスケープされた一重引用符\'(または二重引用符の間に:)"'"を追加してから、一重引用符を再入力して一重引用符を続行する必要があります。 - 引用符付き文字列:たとえば、シェルにコマンドを実行させるには、シェルがgrepに送信するgrep a'b引数を作成できます。'a'\''b'a'bgrep 'a'\''b'grep 'a'"'"'b'

引用符を使用したくない場合は、シェルにaを送信\\して\grepに送信する必要があります。

grep 9\\.0  # ie: a 9, a pair \\, a ., and a 0 , and the shell interprets the pair \\ into a literal \

$vars二重引用符を使用する場合:シェルが最初にいくつかの点(など)を解釈することを考慮する必要があります\。たとえば、エスケープされていないか引用符がないと、\次の文字がどのように解釈されるかを決定するのを待ちます。\w単一文字として扱われるw\\単一文字として扱われる\など

grep "9\\.0"  # looks here the same as not quoting at all... 
    #but doublequoting allows you to have spaces, etc, inside the string

おすすめ記事