検索エンジン自作入門を見ていて、WikipediaのXMLデータから文書を1000件含むXMLファイルを作成するワンライナーが出てきて、非常に勉強になったのでメモ。
ワンライナー
grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml | tail -n 1 | cut -d ":" -f 1 | xargs -I LINE head -n LINE jawiki-latest-pages-articles.xml > 1000.xml
なぜこれで出来るのか
一つずつ実行してみる。
grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml
上のコマンドの意味は
- -mは何件ヒットするまでgrepを続けるか。なので-m 1000で1000件ヒットするまでgrepを続ける
- -nでヒットした行番号を出力してくれる
- Wikipediaの文書は
... で囲まれているので、''を探すと、それぞれの文書の最後の行位置が分かる
というわけで実行すると次のように表示される。
$ grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml 575: </page> 598: </page> 670: </page> ... 235350: </page> 235447: </page> 235491: </page>
この出力に対してtail -n 1
すれば、最後の行が取れるので、
$ grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml | tail -n 1 235491: </page>
となる。
さらにこの出力にcut -d ":" -f 1
すると、:
でsplitし、そのうちの1フィールド目を取ってくれるので
$ grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml | tail -n 1 | cut -d ":" -f 1 235491
とpageの閉じタグが1000回目に出てくる行数が出力される
次にこの出力を以下のコマンドに入力する。
xargs -I LINE head -n LINE jawiki-latest-pages-articles.xml
- -Iは受け取った入力を、xargsで実行するコマンドに展開(置換?)してくれる
- つまり、
echo '235491' | xargs -I LINE head -n LINE jawiki-latest-pages-articles.xml
すると、head -n 235491 jawiki-latest-pages-articles.xml
を実行できる
- つまり、
- head -nでjawiki-latest-pages-articles.xmlの先頭LINE行だけ出力する
$ grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml | tail -n 1 | cut -d ":" -f 1
上のコマンドで、jawiki-latest-pages-article.xmlでpageの閉じタグが1000回目に出てくる行数が出力されているので、
$ grep -m 1000 -n '</page>' jawiki-latest-pages-articles.xml | tail -n 1 | cut -d ":" -f 1 | xargs -I LINE head -n LINE jawiki-latest-pages-articles.xml
で、1000文書が含まれるXMLを出力できることになる。
もちろんXMLとしてvalidなものが出力されるわけではないが、この本ではgrepの速度と全文検索エンジンの速度差を求めたいだけなので、このくらいで十分という感じだった。
まとめ
ワンライナーは奥が深い。