grepで特殊な文字をエスケープしないで検索する
grepでは正規表現で使用する特殊な文字(\、[、]、^、$、*、.など)は、バックスラッシュ(\)を付けて検索する必要があります。1文字ぐらいなら問題ありませんが複数ある場合は手間になります。
この特殊文字をエスケープしないで固定文字して検索する方法を紹介します
「grep -F」で特殊をエスケープしないで検索する
「grep -F 」を使用すると「固定文字列の検索を行う」事ができますので、特殊な文字列をエスケープしないで検索できます
$ cat test.txt abc/def abc\def abc$def abc"def $ grep -F 'c/d' test.txt abc/def $ grep -F 'c\d' test.txt abc\def
但し、「$」を使用する場合は注意が必要です。
検索対象をシングルクォート ‘…’ で囲むか、ダブルクォート “…”で囲むかで対処方法変わってきます。
変数をダブルクォート “…”で囲む場合
ダブルクォート “…”で囲む場合は、対象に$があるとシェル(Bashなど)が以下の手順で実行されます
grep -F "c$d" test.txt の場合
- シェルは、パターン内の
c$dを変数展開しようとします。 - 変数
$dが未定義の場合、空文字列("")に展開されます。 - 結果として
grepに渡されるパターンは"c"となり、ファイル内の全ての行(abc/def,abc\def,abc$def,abc"def)に含まれているため、全てマッチします。
バックスラッシュ(\)でエクケープする必要があります
$ grep -F "c$d" test.txt abc/def abc\def abc$def abc"def $ grep -F "c\$d" test.txt abc$def
変数をダブルクォート シングルクォート ‘…’ で囲む場合
シングルクォートで囲まれた内容は、シェルによる解釈が一切行われません。
grep -F 'c$d' test.txt abc$def # -> grep に "c$d" (リテラル) がそのまま渡される
「fgrep 」で特殊をエスケープしないで検索する
「fgrep」も「grep -F 」と同じで、固定長文字列のでの検索をおこないますので、特殊な文字列をエスケープしないで検索できます
$ cat test.txt abc/def abc\def abc$def abc"def $ fgrep 'c/d' test.txt abc/def $ fgrep 'c\d' test.txt abc\def
但し、「$」の場合は駄目らしく、ダブルクォート “…”で囲む場合は、バックスラッシュ(\)でエクケープする必要があります。シングルクォートで囲む場合はバックスラッシュ(\)は不要です
$ fgrep "c$d" test.txt abc/def abc\def abc$def abc"def # シングルクォートで囲まれた内容は、バックスラッシュは不要 $ fgrep 'c$d' test.txt abc$def # ダブルクォートで囲まれた内容は、バックスラッシュは必要 $ fgrep "c\$d" test.txt abc$def



コメント
$がバッシュの変数として解釈されるためです。
シングルクォーテーションでくくればうまくいきませんか?
ご指摘の通り、ダブルクォート “…”で囲っているので、シェル(Bashなど)の解釈が実行され$を含む場合は変数展開されるので、それを防ぐためにバッククォート(\)が必要となります。
シングルクォート ‘…’ で囲むと、シェルによる解釈が一切行われませんので、$等の変数展開を扱いされずにgrepできます
ご指摘ありがとうございます、記事の方も修正しておきます