2011年06月04日

正規表現を使った置換 - 最強のGUIエディタは?

前回のエントリで書いたように、今回の引っ越しでは一括ダウンロードした記事ごとのHTMLファイルから1個のMT形式ファイルを作成した。その際、合成にはcatコマンドを使い、整形にはエディタの検索・置換機能を使った。今回はその詳細を。

まず、catコマンドだけれど、これはコマンドアレルギーの私なんかが書くよりももっと信頼できる資料を読んでいただくほうがいい。ただ、終わってみて「あそこはこうすべきだった」という反省が2点あるので、そのメモ。
まず、ファイル名が「1.html, 2.html, ..., 9.html, 10.html, 11.html, ..., 100.html, 101.html, ...」という具合の連番になっていたのを、「001.html, 002.html, ..., 009.html, 010.html, 011.html, ..., 100.html, 101.html, ...」と、桁を揃えた正しい連番にリネームしておくべきだったということ。これは、catコマンドで合成したときにファイル名順になるからで、リネームしておかないと1、10、101、102、103、...、199、2、20、201、202、…みたいな変な順番になってしまうからだ。もっともこれは、MT形式でのインポートが済んだ後ではちゃんと日付順にソートされるので最終的には問題はない。ただ、目視でテキストを点検しているときに、日付順が狂っているのがやりにくかったとので、下処理はちゃんとしておくべきだったなと。
次に、コマンドはcat 1.html *.html > combined.txtのようにワイルドカード.*を使ったわけだけれど、このとき合成先のトップの1.htmlの内容が重複することに気がつかなかった。つまり、ワイルドカードで1.htmlも合成ファイルとして指定されてしまうわけだ。だから、正しくは、合成先のファイルを空白のhtmlにするかtxtにすべきだったなと思う。

とまあ、このあたりは瑣末な反省。さて、本命は整形。そして、ここではエディタの検索・置換機能を最大限に利用するわけだが、重要なのは正規表現を使った検索・置換が必要になるということ。

というのは、例えば単純にタグを削除するというのであればふつうに検索・置換すればいいのだけれど、例えばヘッダをごっそり削除したいというようなときには、<head>から</head>までの内容を指定して削除しなければならない。ところが、この間に入ってくる内容は記事ごとに異なるので、ワイルドカードを使わなければ指定ができないからだ。そして、ワイルドカードを指定できるのは正規表現ということになる。正規表現を使えるのはストーリーエディタであるSedということなのだけれど、コマンドで使うこのツールを、当然ながら私は使えない。だから、ここはどうあってもGUIのエディタが必要になるわけだ。ちなみに、正規表現に関する知識は、泥縄でこの辺りを参考にさせていただいた。

調べてみるとgeditに正規表現の検索・置換機能を追加するプラグインがあることがわかった(こちらを参照)。ただ、どういうわけか、このプラグイン、検索機能は正常に動作するのだけれど、置換機能がいまひとつ思ったように動作しない。全く動かないわけではないので、ひょっとしたらこれは正規表現に関する私の知識が不足しているからかもしれない。

どうしようかなと思って調べると、以前、タグ付きの文書の処理で便利に使わせてもらったBluefishというテキストエディタで正規表現の検索・置換機能が利用できることがわかった。そこで久しぶりにこれをインストール。検索・置換のオプションで検索パターンというのがあって、そこで正規表現を選択できる。正規表現にも種類があるらしく、POSIXかPERLを選ばねばならないのだけれど、正直どっちがいいのかわからない。たぶん、ワイルドカードの使用ぐらいなら大差はないのだろう。

ということでBluefishでワイルドカードを使って置換しようとすると、ちょっと困ったことが起こった。というのは、Bluefishでは、ワイルドカードの任意の文字列に改行マークを含めて処理する仕様になっているらしい。つまり、改行マークが無視される。これはこれで、複数行にまたがる任意の文字列を一気にガサッと削除するのに非常に便利なわけだけれど、今回の作業ではこれがアダになる。というのは、例えば上記のヘッダの例だと、454個のhtmlファイルを合成した1個のテキストファイル中には、<head>~</head>で囲まれたヘッダが454個存在する。ところが、改行マークを無視するBluefishの仕様だと、<head>..*</head>は、最初の<head>から最後の</head>まで1個の部分として認識してしまう。そして、ここで検索・置換を行うと、「1個の検索ワードが置換されました」ということになって、最後のボディを除いた全ての情報が削除されてしまうことになる。

ちなみに、geditのプラグインの仕様では、ワイルドカード中の改行マークをはブレイクとして認識される。つまり、改行マークを挟んだ文字列は検索の対象にならない。だから、たとえばリンクを一律に削除したいときなんかは<a href..*">みたいな指定でだいたい確実に対象文字列を拾い上げることができる。ところが改行マークを挟んだ範囲は検索対象にならないので、<head>..*</head>みたいな検索では「指定の文字列がありません」ということになってしまう。
ただ、こういう仕様の場合、いったん改行マークをなにか特徴のある(本文中では絶対に使われていない)文字列(たとえばギリシア文字)に一括置換しておいてその中から特徴的なブレイクだけ改行マークに再変換することで、うまい具合にワイルドカードで望む文字列をヒットさせることができる。それがわかっているだけに、geditのプラグインがうまく使えないのがもどかしくて仕方ない。

そのとき、ふと思いついた。OpenOffice(というかLibreOffice)のWriterで正規表現の検索・置換機能が使えなかっただろうか。見てみると、詳細オプションの中に正規表現のチェックボックスがある。これは、geditのプラグインと同じで改行マークをブレイクと認識する仕様。これは使えそうだと、Writerにテキストをコピー&ペーストしてやって処理。大半の処理はこれでうまくいった。

ということで、「正規表現検索・置換の最強GUIエディタは実はLibreOfficeだった!」というオチにするつもりのこの記事だったのだけれど、実は続きがある。

今回の引っ越しで、引っ越し後1ヶ月ぐらいは旧ブログの各記事に「引っ越しました。引越し先はこちらです」という感じのメッセージを入れようと思っていた。そして、旧ブログ記事は個別のHTMLファイルとして存在する。となると必要なのは、複数ファイルを横断的に検索・置換できるソフトだ。
そういうものとして、以前、Quantaに付随する(単独でもインストールできる)KFileReplaceというバッチ処理型のツールを利用したことがあった。今回もそれを使ってもよかったのだけれど、先に試したBluefishに、「開いている全てのファイル」を対象にするオプションがあるのに気がついていた。オフィシャルページに行ってみると、「難なく500以上の文書を開けます」と書いてある。そこで、100以上あるファイルを一気に開いてみると、あっさりと開けた。そして、<body>..*</body>で指定すると、各文書の内容がほとんど一瞬で引っ越し案内に置き換わった。

つまり、手順として最初に複数のHTMLファイルを1つにまとめるのではなく、複数ファイルのままBluefishで処理をしてから1ファイルにまとめる方式でやったら、たぶんLibreOfficeよりもBluefishのほうが処理が早かっただろうという感じ。特に、LibreOfficeでは改行マークを指定文字列や置換文字列に含めることができないので、そういう必要があるときはgeditにいちいち戻って処理する必要があった。Bluefishならそれもうまくいくわけで、どう考えてもこっちのほうが勝ちだろう。

ということで、改めて「正規表現検索・置換の最強GUIエディタはBluefishだった」という結論。ま、何が「最強」かというのはもちろん作業の目的によって変わってくるので、これはあくまでひとつの事例での話として聞いて頂ければということではあるけれど。

何にしても、今回、引っ越しのデータ移行は、思ったよりもスムーズにいった。実際にはリンク切れとか動画の貼りつけ処理がおかしくなっているところとか、いろいろ細かな修正はまだまだ必要になりそうだ。それでも、大筋として一段落ついて、ちょっとほっとしている。

posted by 松本 at 09:43| Comment(0) | TrackBack(0) | 総記・雑記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック