私はこの質問のいくつかのバージョンが以前に質問され答えられたと確信していますが、周りを見回しましたが、明確な答えが見つかりませんでした。たぶんここで誰かが電球をつけるのを手伝ってくれるかもしれません。私は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/g
3つの文字列9.00
9-00
と9500
。
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'b
grep '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
答え2
コメントを回答に変換:
問題は、これが\
正規表現であり、シェルエスケープ文字であるということです。\.
シェルと同じです'.'
。シェルの役割を理解するのに役立つように、次の手順を実行しますecho
。set -x
> echo \.
.
> echo '\.'
\.
> echo \\.
\.
> set -x
> echo 9_00 | grep 9\.00
+ echo 9_00
+ grep 9.00
9_00
したがって、コマンドを表示するには、引用符または\
2番目の引用符で保護する必要があります\
。
答え3
他の回答やコメントを追加するには、grep
次のコマンドを使用して必要なものを返します。
grep -F 9.00 small.txt
出力:
9.00
makeはパターンを正規表現ではなく固定文字列として-F
扱うので、grep
正確な文字列を持つ行のみを返します。したがって、正確に一致するだけで文字として扱われないため、エスケープや.
引用符を使用する必要さえありません。9.00
.
答え4
grepの正規表現ではエスケープ文字を引用する必要がありますが、オンライン正規表現エンジンでは引用しないでください。
あえて引用する必要はないgrepしかし、シェルの場合。
grep -f
ファイルからパターンを読み取ると、表示されたパターンが9\.00
シェルを通過しなくても正常に動作することがわかります。
$ cat re.txt
9\.00
$ grep -f re.txt small.txt
9.00
実際、問題grep
自体は問題ではないため、正規表現に関する記事で問題を見ることができない可能性があります。しかし、シェルがどのように機能するかについての記事では、関連事項を見ることができます。
プレミアムエンジンには違いがあることを知っています。
あまり進化する必要もありません。+
BREとEREの同様の機能が変更されました。さらに、少なくとも一部のオンラインツールはデフォルトでPerl正規表現または同様のツールを使用しています。
望むより: