前回までに、フィルタコマンドの活用方法について、grep(1)を例に挙げて解説してきた。ここまでに解説した内容だけでも、かなりのことができるようになるのだが、grep(1)にはさらに便利な機能として「パターンに一致した行の前の行を表示する」、または「パターンに一致した行の後の行を表示する」という機能が用意されている。これらはいずれも「かゆいところに手が届く」便利な機能だ。今回は、この機能について取り上げようと思う。
一致した行の前を表示するオプション「-B」
フィルタとして利用できるコマンドでは、そのほとんどの処理の単位は「行」となっており、全て行単位で処理を行う。パターンの一致も、そこからの変換も、行単位で行うことが基本だ。grep(1)も基本的には行単位で処理が行われるのだが、機能の1つとして「パターンに一致した前の行を出力する」といった仕組みが用意されている。
「それが一体どうした」と思うかもしれないが、現実の作業では、そういった処理をしたくなるテキストデータに遭遇することがある。そういう状況に陥った時、この機能があるとないのとでは作業負荷が雲泥の差になるのだ。
次のサンプルドキュメントを見てほしい。
これは、「tttcmds」というコマンドセットの説明文をマークダウンという形式で書いたものだ。このマークダウン形式のドキュメントは、整形後にWebブラウザで見ると次のように見える。
このマークダウンは「=====」の前の行に見出し、「——-」の前の行に小見出し、「## 」の行に小々見出し、といった記述になっている。もし、「この『見出し』の部分だけを取り出してテキストに変換し、目次を作りたい」という場合、「## 」の行で始まっている小々見出しは前回までに説明してきたフィルタコマンドの機能で抽出できるが、「=====」と「——-」は取り出せない。
そこで登場するのが、オプション「-B」だ。同オプションを利用すると、条件に一致した行の前の行を取り出すことができる。-Bオプションには、前の行を何行分出力するのかを指定して使用するため、今回の例の場合は「-B 1」という指定することになる。
% cat doc | grep -E -B 1 '(^=+$)|(^-+$)'
TTT COMMANDS
============
--
Download
--------
--
Installation
------------
%
ちなみに、フィルタ系のコマンドをつなげると「## 」の見出しも含めて見出し系のデータだけを抜き出し、次のように目次っぽいデータに整形することもできる(ただし、あまりお薦めする使い方ではない)。
% cat doc |
> gsed 's/^## \(.*\)$/\1\n##/' |
> grep -E -B 1 '(^=+$)|(^-+$)|(^#+$)' |
> grep -v -- '^--$' |
> tail -r |
> tr '\n' '\t' |
> gsed -e 's/##\t/ o /g' -e 's/--*\t/ - /g' -e 's/==*\t//g' |
> tr '\t' '\n' |
> tail -r
TTT COMMANDS
- Download
- Installation
o required packages installation
o build and install
%
このようにコマンドをつなげると、いよいよ呪文じみて見えるかもしれない。この手のフィルタコマンドは、書いている時には覚えているが、後から見ると何をするための記述だったかがわからなくなっていることがよくある。そのため、必要になったらサクッと書いて、過去のスクリプトを見て内容が思い出せなかったらまた書き直す……くらいのつもりでいればよいと思う。
一致した行の後を表示するオプション「-A」
オプション「-B」とは逆に、一致した行の次の行を出力したい場合にはオプション「-A」を使う。使用する際は、-Bオプションと同じく何行分を出力するかを指定する。データ形式のなかにはデリミタとなる文字列が行データとして入っていて、その次の行にデータが書いてあるといったものもある。ちなみに、-Aオプションと-Bオプションを同時に適用するような「-C」というオプションも用意されている。これは、「一致した行の前後を表示する」ことを指定するオプションだ。
フィルタ系のコマンドは、基本的にはデータが行単位になっている場合に便利な機能だ。そのため、必要なデータが行をまたぐような場合は何をやってもだいぶ面倒な処理になる。ただし、欲しいデータがgrepの-Bオプション、または-Aオプションの利用で抽出できる範囲なら、サクッと作業を終わらせることができるだろう。覚えておいて損はしない機能だ。「こういうことができる」ということさえ覚えておけば、指定するオプションが何だったかについては、必要になった時に調べればよい。