檜山正幸のキマイラ飼育記 このページをアンテナに追加 RSSフィード

キマイラ・サイトは http://www.chimaira.org/です。
トラックバック/コメントは日付を気にせずにどうぞ。
連絡は hiyama{at}chimaira{dot}org へ。
蒸し返し歓迎!
ところで、アーカイブってけっこう便利ですよ。タクソノミーも作成中。今は疲れるので作っていません。

2008-04-04 (金)

grepコマンドとEmacs grepモードって、やっぱり便利だよな

| 16:10 | grepコマンドとEmacs grepモードって、やっぱり便利だよなを含むブックマーク

grepコマンド、それとEmacsのM-x grepgrepモードって、かなり便利ですよ。プログラミング以外の用途でもいろいろ使えます。

WindowsでもUnix系OSでもほとんど同じですが、差がある部分は括弧内に示します。

例題の説明

僕は、はてなダイアリーをブラウザから直接書くことはあまりなくて、前もってテキストエディタで書いたものを貼り付けています(これは事実)。各分類カテゴリごとにファイルを分けて、hatena-nitijo.txt, hatena-zakki.txt, hatena-memo.txtとなっているとしましょう(事実じゃない、あまり整理してない ^^;)。

はてな記法では、行頭に「*」があるとエントリータイトルなので、次のコマンドで全エントリータイトルを列挙できます(Unix系では、ダブルクォートの代わりにシングルクォートを使用してください)。

 grep "^\*" hatena-*.txt

grepコマンドの場合は星印「*」をエスケープする(「\」を付ける)必要はないのですが、正規表現一般の構文としてはエスケープすべきですね。

さて、出力はこんな感じ。

hatena-memo.txt:*t*[雑記/備忘][檜山用メモ]リネームとサブタイプと置換原則
hatena-memo.txt:*t*[雑記/備忘][檜山用メモ]積と指数の随伴に関する練習問題
hatena-nitijo.txt:*t*[日常]考えない勇者
hatena-nitijo.txt:*t*[日常]聞いてしまったTV番組企画
... (省略)

-nオプションで行番号を付ける

 grep -n "^\*" hatena-*.txt

と、-nオプションを付ければ、タイトルが出現した行の番号も表示されます。

hatena-memo.txt:2:*t*[雑記/備忘][檜山用メモ]リネームとサブタイプと置換原則
hatena-memo.txt:364:*t*[雑記/備忘][檜山用メモ]積と指数の随伴に関する練習問題
hatena-nitijo.txt:1:*t*[日常]考えない勇者
hatena-nitijo.txt:12:*t*[日常]聞いてしまったTV番組企画
... (省略)

ファイル名と行番号が付いた出力は、いろいろな場面で大変有効に使えます。

ファイル指定にnul(/dev/null)を含ませておこう

ちょっとした落とし穴があります。

例えば、hatena-memo.txt内に1つしかエントリーがないとき、*1hatena-memo.txtだけをコマンドラインに指定したら、grepの出力はどうなるでしょうか? こうなります。

2:*t*[雑記/備忘][檜山用メモ]リネームとサブタイプと置換原則
364:*t*[雑記/備忘][檜山用メモ]積と指数の随伴に関する練習問題

ファイル名が省略されてしまうのです。hatena-*.txt のようにワイルドカードを使っていても、マッチするファイルがhatena-memo.txtだけなら同じ出力になります。

手動でgrepを起動しているならたいした問題ではないのですが、バッチファイル(シェルスクリプト)内でgrepを使っているときは変なことになるかもしれません。

 grep -n "^\*" nul hatena-*.txt > hatena-entries.grep

のように、nul(/dev/null)をファイル指定に入れておくといいでしょう。

Emacsからgrepコマンドを使う

Emacs内からgrepするには、M-x grepです。上で述べた注意事項は、Emacsが気を使ってくれるので安心です(パターン先頭が「-」である事態も想定して、-eオプションも付けてくれます)。

キーボードから "^\*" hatena-*.txt を入力すると、コマンドラインから

grep -n -e "^\*" hatena-*.txt NUL

としたのと同じになります。最後のNUL(/dev/null)はEmacsが付けてくれます。

Emacsgrepモードを使う

便利なのはここからです。grepの出力が取り込まれたバッファは自動的にgrepモードになります。ほらっ、きれいにカラーリングされているでしょ。カラーリングだけじゃないですよ、*grep*バッファに移ってのn(next-error-no-select)とp(previous-error-no-select)がすごーく便利(下の画面参照)。エントリータイトルと第1段落をザッとブラウズするのに最適。


原寸大

タイトルに対応する本文(hatena-*.txt)内の位置にカーソル移動するには、RETまたはC-c C-c(compile-goto-error)です。本文に移ってからも、C-x `(next-error)で次から次へとエントリーをブラウズできます。M-g nでもC-x `と同じ。これらと対になるコマンドはM-g p(previous-error)です。

ファイルを自動的にgrepモードで見る

僕は、コマンドラインからのgrep出力をファイルに取っておくことがあります。

 grep -n "^\*" nul hatena-*.txt > hatena-entries.grep

hatena-entries.grepEmacsに読み込みます。そして、M-x grep-modeとすれば、上記と同じ状態になります。

.grep拡張子(なんでもいいけど)から自動的にgrepモードにするには、.emacs内に次のように書いておきましょう。

(add-to-list 'auto-mode-alist 
             (cons "\\.grep$" 'grep-mode))

*1:「1つしかエントリーがない」って、なんで書いたのだろう? 今となっては意味不明。たぶん、「1つしかファイルがない」と混乱して書いてしまったのだと思います。