$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

WikipediaのXMLデータから文書を1000件含むXMLファイルを作成するワンライナー

検索エンジン自作入門を見ていて、WikipediaXMLデータから文書を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の速度と全文検索エンジンの速度差を求めたいだけなので、このくらいで十分という感じだった。

まとめ

ワンライナーは奥が深い。