レガシーなシステムでは、Linux サーバ上に Shift JIS (cp932) でソースコードが書かれていることがある(特に HTML テンプレートファイルなど)。
Shift JIS ソースコードで grep が動かない!
その場合、日本語文字列を grep する方法として、ネットでは以下のような方法が書かれていることが多い。
# これは、うまくいかない hoge@hoge:~> grep -rn `echo "こんにちは" | nkf -s` ./
これは、nkf コマンドで対象文字列を UTF-8 から Shift JIS に変換し、それを grep コマンドに渡す方法である。
しかし、実際にはこれでは1件もヒットしない事象が発生してしまった。
find コマンドと -exec オプションで解決
いろいろ試行錯誤した結果、find コマンドで -exec オプションを使うことで、なんとか grep もどきの動作を実現できた。
# Shift JIS に限らないならこれ hoge@hoge:~> find ./ -type f -exec bash -c 'nkf -w {} | grep -n "こんにちは" && echo {};' \; # Shift JIS に限るなら nkf コマンドに -S オプション(入力文字コード明示)を付ける # (付けないと絵文字などが入っている行の変換がうまくいかないことがある) hoge@hoge:~> find ./ -type f -exec bash -c 'nkf -Sw {} | grep -n "こんにちは" && echo {};' \; 2: <h2>みなさん、こんにちは</h2> ./Hoge/Hoge.html 130: <td><a href="#hoge">こんにちはです</a></td> ./Hoge/Hoge2.html ### ファイル名だけ検索ならこれ hoge@hoge:~> find ./ -type f -exec bash -c 'nkf -w {} | grep -q "こんにちは" && echo {};' \;
各コマンドの説明
- find ./ -type f コマンドは、カレントディレクトリ以下のファイルを列挙する。
- 列挙したファイルは {} で参照する。
- -exec オプションは、列挙した各ファイルに対しコマンドを適用する方法。
- bash -c コマンドは、コマンド文字列を読み込んで実行する。
- nkf -w コマンドは、対象ファイルを読み込み、そのエンコーディングを推測した上で UTF-8 に変換して標準出力に出す。
- | grep -n “こんにちは” コマンドは、上記コマンドの出力を受け取り文字列 “こんにちは” が見つかれば(マッチすれば)出力する。
- && echo {} は、上記 grep がマッチした時(1を返す)、そのファイル名を出力する。(これを出さないと、何のファイルがマッチしたか分からない^^;)
- ; はコマンドの終了を表す。しかし、シェルに「;」を解釈させず、find へ「;」を渡すためにエスケープしてある。また、「{}」と「\」の間には必ずスペースを空けなくてはならない。
コメント