どして
grep e\\.g\\. <<< "this is an e.g. wow"
そして
grep e\.g\. <<< "this is an e.g. wow"
同じことをしますか?
3つ目のスラッシュを追加しても、同じ結果になります。しかし、4つ目のスラッシュを追加すると機能しなくなります。これは、クラスの古い試験の質問に関係しています。 2つのバックスラッシュのあるものは、「e.g。」最初はうまくいかないと思っていましたが、確認してみました。説明は何ですか?
最初に、単一のスラッシュは一致しすぎていることに注意してください。
$ echo $'eegg \n e.g.' | grep e\.g\.
eegg
e.g.
Bash に関する限り、エスケープされたピリオドはピリオドと同じです。 Bashはピリオドを grep に渡します。 grepの場合、ピリオドはすべてに一致します。
さて、考慮してください:
$ echo $'eegg \n e.g.' | grep e\\.g\\.
e.g.
$ echo $'eegg \n e.g.' | grep e\\\.g\\\.
e.g.
$ echo $'eegg \n e.g.' | grep e\\\\.g\\\\.
$
Bashが二重スラッシュを見つけると、それを単一のスラッシュに減らし、それをgrepに渡します。grepは、上記の3つのテストの最初で、必要に応じて、ピリオドの前に単一のスラッシュを見つけます。したがって、これは正しいことを行います。
トリプルスラッシュの場合、Bashは最初の2つを1つのスラッシュに減らします。次に\.
。エスケープ期間はBashにとって特別な意味がないため、これはプレーン期間に短縮されます。その結果、grepは、必要に応じてピリオドの前にスラッシュを表示します。
4つのスラッシュを使用して、Bashは各ペアを1つのスラッシュに減らします。 bashは、2つのスラッシュとピリオドをgrepに渡します。 grepは2つのスラッシュとピリオドを認識し、2つのスラッシュを1つのliteralスラッシュに減らします。入力に任意の文字が続くリテラルスラッシュがない限り、一致はありません。
最後に、単一引用符内ではすべての文字がリテラルであることを思い出してください。したがって、次の3つの入力行を指定すると、grepコマンドは、入力にリテラルスラッシュが含まれる行でのみ一致します。
$ echo 'eegg
e.g.
e\.g\.' | grep e\\\\.g\\\\.
e\.g\.
バッシュの場合、ルールは
2つのスラッシュは1つのスラッシュに削減されます。
ピリオドのような通常の文字の前のスラッシュは、通常の文字(ピリオド)にすぎません。
したがって:
$ echo \. \\. \\\. \\\\.
. \. \. \\.
このすべての混乱を回避する簡単な方法があります。Bashコマンドラインでは、正規表現を単一引用符で囲む必要があります。単一引用符内では、Bashはすべてをそのままにします。
$ echo '\. \\. \\\. \\\\.' # Note single-quotes
\. \\. \\\. \\\\.
出力は文字列に対してのみ同じですが、一般的にこれらの正規表現は異なることを行います。 2番目のパターンe,g,
(comas付き)、3番目のe\.g\.
(ドット)、4番目のe\,g\,
(comas)、および-o
オプションをgrepに追加して、例を少し変更してみましょう一致した部分のみを印刷します。
次の場合、.
は任意の文字に一致します(''
の周りのe.g.
に注意してください。後でそのことに行きます)。
$ grep -o 'e.g.' <<< grep -o 'e.g.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e.g.
e,g,
次に、.
をバックスラッシュ\
でエスケープするため、リテラル.
のみが一致します。
$ grep -o 'e\.g\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e.g.
しかし、\
を別の\
でエスケープして、リテラル\
に.
(つまり任意の文字)を続けて照合できます。
$ grep -o 'e\\.g\\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e\.g\.
e\,g\,
ただし、\.
ではなく\,
のみに一致させたい場合は、ドットの特別な意味をエスケープするために、さらに\
が必要です。
$ grep -o 'e\\\.g\\\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e\.g\.
ここで、grep引数の周りに''
を使用しなかったため、バックスラッシュをシェルの解釈からエスケープするために別のバックスラッシュを追加する必要があります。
grep 'e\.g\.' => grep e\\.g\\.
grep 'e\\.g\\.' => grep e\\\\.g\\\\. (each backslash has to be quoted separately)
grep 'e\\\.g\\\.' => grep e\\\\\\.g\\\\\\. (3 x 2 = 6 backslashes in total)
grep e\.g\.
を実行すると、シェルはバックスラッシュを消費するため、一致するgrep e.g.
を実行します。 grep e\\.g\\.
を実行すると、シェルは再びスラッシュを消費し、今度は再び一致するgrep e\.\g.
を実行しています。これで、シェルへのバックスラッシュは\\
のようになります。したがって、\\
がある場合、最初のエスケープシーケンスはエスケープシーケンスで、2番目はリテラルのバックスラッシュです。最初にgrep e\\\.g\\\.
をリテラルにするgrep e\.\g.
の前にエスケープシーケンス(\
)がないため、\
を実行しても、最終的には\
になります。 SOMECODE] _。 \はバックスラッシュであるため、grep e\\\\.\\\\g
はgrep e\\.g\\.
になり、明らかに一致しません。
シェルが実行していることをシェルがどのように認識しているかを確認するには、echoを使用します(例:echo grep e\\.g\\. <<< "this is an e.g. wow"
とecho grep e\\\\.g\\\\. <<< "this is an e.g. wow"
)
2つのコマンドは、入力に対してのみ同じ出力を生成しますが、それ以外は異なります。何が起こっているのかを理解するには、最初にbash
によって、次にgrep
によってパラメーターがどのように解釈されるかを知る必要があります。
\
は、\
自体を含む後続の文字の特別な意味を取り消す特殊文字です。次の文字に特別な意味がない場合は、そのまま渡されます。コマンドと結果の例:
echo \a
:a
—エスケープされた通常の文字が文字を与えるecho \\
:\
—エスケープされた特殊文字が文字を与えるecho \\\a
:\a
—特殊な組み合わせ、通常echo \\\\
:\\
—特別な組み合わせ、特別な組み合わせecho
は、bash
が解釈した結果の文字列を出力します。詳細: bashのドキュメント 、 bash hackers wiki 、 POSIX仕様 。
.
はbash
では特別な意味を持ちません。シェルの普通のキャラクターです。以下は、例に関連するシーケンスです。
echo .
:.
echo \.
:.
echo \\.
:\.
echo \\\.
:\.
echo \\\\.
:\\.
文字通りbash
でパラメータを渡すには、単一引用符'
エスケープを使用できます。一重引用符の間では特別な意味を持つ唯一の文字であるため、文字の特別な意味を気にする必要はありません。文字列の最初の部分を囲んだ後、一重引用符を挿入できます。例:echo 'part1'\''part2'
:part1'part2
\
は、bash
と同様の意味を持つエスケープ文字です。 .
は任意の文字の1つの出現を表すの特殊文字です。 POSIX regex 、 GNU grep regex を参照してください。正規表現の例:
.
— a
や.
などの任意の文字に一致します\.
—文字どおり.
のみに一致以下のすべての例の2行目に、bash
からgrep
に渡されるリテラル文字列を示す、単一引用符'
で同等のものがあります。次に、grep
がエスケープを実行した後、例で使用できる特殊文字は.
で、任意の文字に一致します。 3行目には、式が一致する内容の説明があります。
grep e.g. <<< "this is an e.g. wow"
grep 'e.g.' <<< "this is an e.g. wow"
e
任意の文字g
任意の文字— e.g.
と一致し、場合によっては他の文字列eagb
と一致grep e\.g\. <<< "this is an e.g. wow"
grep 'e.g.' <<< "this is an e.g. wow"
e
任意の文字g
任意の文字— e.g.
と一致し、場合によっては他の文字列exgy
と一致grep e\\.g\\. <<< "this is an e.g. wow"
grep 'e\.g\.' <<< "this is an e.g. wow"
e.g.
文字通り— e.g.
のみに一致grep e\\\.g\\\. <<< "this is an e.g. wow"
grep 'e\.g\.' <<< "this is an e.g. wow"
e.g.
文字通り— e.g.
のみに一致grep e\\\\.g\\\\. <<< "this is an e.g. wow"
grep 'e\\.g\\.' <<< "this is an e.g. wow"
e\
任意の文字g\
任意の文字— しない一致e.g.