私は最近、コマンドラインでいくつかの正規表現に問題があり、バックスラッシュを一致させるために、異なる数の文字を使用できることがわかりました。この数は、正規表現に使用される引用符(なし、単一引用符、二重引用符)に依存します。意味については、次のbashセッションを参照してください。
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
この意味は:
- 引用符なしで、バックスラッシュを4〜7個の実際のバックスラッシュと一致させることができます。
- 二重引用符を使用すると、バックスラッシュを3〜6個の実際のバックスラッシュと一致させることができます
- 単一引用符を使用すると、バックスラッシュを2〜3個の実際のバックスラッシュと一致させることができます
1つの余分なバックスラッシュがシェルによって無視されることを理解しています(bashのマニュアルページから)。
「引用符で囲まれていないバックスラッシュ(\)はエスケープ文字です。次の文字のリテラル値を保持します」
これは、単一引用符でエスケープされないため、単一引用符で囲まれた例には適用されません。
また、追加のバックスラッシュはgrepコマンドによって無視されます(「\ c」はエスケープされた「c」ですが、「c」は正規表現では特別な意味を持たないため、「c」と同じです)。
これは、単一引用符を使用した例の動作を説明しますが、他の2つの例、特に非引用符付き文字列と二重引用符付き文字列に違いがある理由はよくわかりません。
繰り返しますが、bashのmanページからの引用:
「二重引用符で文字を囲むと、引用符内のすべての文字のリテラル値が保持されます。ただし、$、 `、\、および履歴展開が有効になっている場合は!。
GNU awk(例awk /ab\cd/{print} file
)でも同じことを試みましたが、同じ結果になりました。
ただし、Perlでは異なる結果が表示されます(例perl -ne
"/ab\\cd/"\&\&print file
:を使用)。
- 引用符なしで、バックスラッシュを4〜5個の実際のバックスラッシュと一致させることができます。
- 二重引用符を使用すると、バックスラッシュを3〜4個の実際のバックスラッシュと一致させることができます
- 単一引用符を使用すると、バックスラッシュを2つの実際のバックスラッシュと一致させることができます
grepとawkのコマンドラインで、引用符で囲まれていない正規表現文字列と二重引用符で囲まれた正規表現文字列の違いを誰でも説明できますか?私は通常Perlのワンライナーを使用しないため、Perlの動作の説明にはそれほど興味がありません。
printf "\ntest"
であるにもかかわらず、「test」の前に改行を挿入します...(期待される結果は、 「\ ntest」、「ntest」。私たちは書く習慣を身につける必要があります:または 、しかし、どういうわけか奇妙なことに依存する多くのスクリプトが表示されます"\n"
"n"
printf "\\ntest"
printf '\ntest'