先日、ブログを移行しました。その作業の一環で元データのHTMLコードから不要な個所をまとめて消す必要がありました。その正規表現を書くのに苦戦したので、記録を残しておきます。
やりたいこと→特定のタグに挟まれた部分を一括選択する
▼下記のようなHTMLコードの一群(1~11行目)を、まとめて消す必要がありました。
この一群は<ul class="table-of-contents"></ul>
で囲まれた目次のリストなんですが、 1ファイルに200か所ほど存在し、手作業では消しきれません。
そこで、テキストエディタを使って正規表現で一括選択・置換して消そうと思います。
結果
結果的には、以下の表現で選択できました。
↓検索
<ul class="table-of-contents">((?!<ul).*\n)*?</ul>\n*<h2
↓置換
<h2
補足
</ul>
は至るところで出てくるので、どこが目次の終わりかを示さねばなりません。
元データを見ると改行0~2回後にh2見出しが入るという規則があったので、改行が0回以上\n*
という指定をしています。
使ったエディタ
使ったテキストエディタは、Meryです。
ものすごく使いやすくて、気に入っているエディタです。
どうして苦戦したか
元ファイルは今まで書いたブログ記事が全て記録されていて、 3万行以上あるファイルです。
「正規表現で一括で消せばいいだろう」とか軽く考えていましたが、私の知識不足でその表記を書くのにてこずってしまいました。
複数行にわたるコードをうまく選択できないんです。
↓とりあえず決まったタグで囲まれているので、最初こんな表現で試しました。
ちゃんと最短一致*?も付けました。
<ul class="table-of-contents">(*\n)*?</ul>\n*<h2
↓そしたらこんな結果に……
一回目の <ul class="table-of-contents">
から、n回目のオケツの</ul>
までの間が全て選択されてしまう箇所がでてきました。
原因は、目次の直後にh2タグが来るとは限らず、見出しが無くて<p>
タグの場合もあるから……ということが眺めているとわかりました。
↓そこで否定先読み(?!<ul)
を入れて、目次リストの中身に<ul
が含まれていたら選択しないようにしました。
<ul class="table-of-contents">((?!<ul).*\n)*?</ul>\n*<h2
さいごに
冒頭でも書きましたが、いきなり本番で検索・置換するのは禁物です。
私は3万行以上の本番ファイルでやってしまい、PCのファンがフォ~と回りだして固まってしまい、めっちゃ焦りました。