回答:
最初に、単一のスラッシュは一致しすぎていることに注意してください。
$ echo $'eegg \n e.g.' | grep e\.g\.
eegg
e.g.
限りバッシュが懸念され、エスケープ期間は、期間と同じです。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つのリテラルスラッシュに減らします。入力に任意の文字が続くリテラルスラッシュがない限り、一致はありません。
最後に、単一引用符内ではすべての文字がリテラルであることを思い出してください。したがって、次の3つの入力行が与えられた場合、grepコマンドは、入力にリテラルスラッシュが含まれる行でのみ一致します。
$ echo 'eegg
e.g.
e\.g\.' | grep e\\\\.g\\\\.
e\.g\.
Bashの場合、ルールは
2つのスラッシュは1つのスラッシュに削減されます。
ピリオドのような通常の文字の前のスラッシュは、通常の文字(ピリオド)にすぎません。
したがって:
$ echo \. \\. \\\. \\\\.
. \. \. \\.
このすべての混乱を回避する簡単な方法があります。Bashコマンドラインでは、正規表現を単一引用符で囲む必要があります。単一引用符内では、Bashはすべてをそのままにします。
$ echo '\. \\. \\\. \\\\.' # Note single-quotes
\. \\. \\\. \\\\.
echo
これらのケースでbashが何をするかを説明するステートメントについては、更新された回答を参照してください。
\.
か.
。bashの場合、これらは両方とも同じです。これらは通常のピリオドと同等です。したがって、全体として、bashがgrepに提供するものはどちらも同じです。つまり、単一のスラッシュとそれに続くピリオドです。
echo
このプログラムの多くの実装のため、使用は正規表現をテストするための非常に信頼できる方法ではありません。たとえば、私のzsh(組み込みのエコー)では、が返されますecho \. \\. \\\. \\\\. \\\\\.
が. \. \. \. \.
、が/bin/echo \. \\. \\\. \\\\. \\\\\.
返されます. \. \. \\. \\.
。のようなものprintf "%s" ...
がおそらくより良い方法です。
出力は文字列に対してのみ同じですが、一般的にこれらの正規表現は異なることを行います。2番目のパターンe,g,
(コンマ付き)、3番目e\.g\.
(ドット)、4番目e\,g\,
(コマ)、および-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.
エスケープシーケンス(存在しないので、\
最初の前に)\
それリテラルにします\
。このように、バックスラッシュは\を覚えておいてくださいgrep e\\\\.\\\\g
されて終わるgrep e\\.g\\.
明らかに一致しません、。
シェルが何をしているかを確認するには、echoを使用します(例:echo grep e\\.g\\. <<< "this is an e.g. wow"
vs. 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ハッカー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.
\\\.
grep を取得して提供すると考え\.
ていましたが、そうではありません。良い質問