質問: bashで正規表現の検索パターンとして`$`記号を指定したいのですが、エスケープが必要ということは理解しているのですがエスケープはバックスラッシュを直前に1つ入れると理解しているのですが、この場合`\$`ではうまくいかず`\\$`のようにバックスラッシュを2つ差し込むとうまく動くのですがなぜ1つではダメなのでしょうか? ``` export GREP_OPTIONS='--color=always' echo I love $ | grep \\$ I love $ echo I love $ | grep \$ I love $ ``` 上記のコードでは色付けされていませんが、手元のbashではバックスラッシュを2ついれると`$`記号が赤字で出力されるのですが、1つだと黒字で出力されています。 初歩的な質問で申し訳ありませんが、回答よろしくお願いします。 マルチポスト
回答: 質問冒頭 > > bashで正規表現 > > > という表現がそもそもの問題がどこにあるかを正しく理解できていないことを示しています。bashももちろん正規表現を扱うことがありますが、今回は無関係です。 今回、bashはgrepという外部プログラムを起動するだけです。 grepとしても`$`は行末を表すメタ文字ですので、この機能をキャンセルするためには`\`でエスケープする必要があります。つまりgrepが受け取るべき引数文字列は`\$`です。 次にbashにおいて、`\`はエスケープ記号、`$`は変数の接頭辞とどちらも特殊な機能を持つためそれぞれ`\`でエスケープする必要があります。つまりbashに入力すべき文字列は`grep \\\$`となります。 この手のエスケープをエスケープしてわけがわからなくなることを傾斜爪楊枝症候群と呼ばれています。 > > grep \$ とバックスラッシュが2つでも同様の出力結果が得られ、書籍ではそのように記述されているのですが同様の結果が得られるのはどういう解釈をすれば理解できるのでしょうか? > > > 「バックスラッシュを2ついれると$記号が赤字で出力される」とあるように異常状態を示しています。先に説明したとおり、bashにとって`$`は変数の接頭辞なため、`$`の後ろには変数名が続くべきです。それがないため赤字で警告しています。 バックスラッシュ2つは正しくはありませんが、bashは変数としての解釈を諦め`$`をそのままgrepに渡すため、結果として`grep \\$`は`grep \\\$`と同じとなります。 もし書籍にそのような記述がなされているのであれば、筆者の知識が浅いのか、このような説明を端折ったかのどちらかで、どちらであってもろくな書籍とは言えないような気がします。 > > echoコマンドに関しては $ を出力したい時に引数に echo \$ とバックスラッシュ1つで意図通りの出力結果が得られますが、この場合も echo \\$ と記述しなくてよいのはなぜでしょうか? grepコマンドに引数として渡す場合とでバックスラッシュの記述の仕方が変わるのはなぜなのでしょうか? > > > **bash、echo、grepとそれぞれ立場の異なる3つのプログラムに分けて解釈する必要があります。** grepは正規表現として`$`を特別視します。しかしechoは`$`を特別視しません。ですからechoが受け取るべき引数文字列は`$`となります。次にbashにおいて、`$`は変数の接頭辞と特殊な機能を持つため`\`でエスケープする必要があります。つまりbashに入力すべき文字列は`echo \$`となります。