あるタグで囲まれた領域だけに正規表現を適用する方法
あるタグで囲まれた領域だけに正規表現を適用する方法
正規表現を使うとき、毎回調べなおすので、まとめておこうと思う。
Perlやsedに始まり、UN*Xの文化とも言える regular expression だが、「正規表現」という堅苦しい名称はその難解さを体現しているとも言える。
同じくUN*X文化のviは一度その難解な使い方を身に着けてしまうと、指をキーボードのホームポジションに置いたまま作業ができるという長所がある。
それに比べて、正規表現というやつは、したいことを実現しようとすると、最低でも数時間は試行錯誤することになる。
先日、こんな問題にぶちあたった。
<問題>
HTMLの中で< code>< /code>タグで囲まれた部分から< p>タグをすべて取り除く。
<実装> PHPの場合
mb_regex_encoding("utf8");
$html = "< p>第一段落< /p>< code>
< p class="plus">
foreach ($array as $data) {
$image = $data;
}
< /p>
< /code>< p>第三段落< /p>
< code>if (1) else fi< /code>";
$pattern_code = "(?<=< code>)((\n|.)*?)(?=<\/code>)";
function func_remove_p($matches) {
$tmp = mb_ereg_replace("< p class=\"plus\">", "", $matches[1]);
return mb_ereg_replace("< /p>", "", $tmp);
}
// 正規表現パターンに一致した箇所が見つかったらcallback関数を毎回呼ぶ
$honbun = preg_replace_callback("/$pattern_code/", "func_remove_p", $html);
<ポイント>
2段階に分けて手続きを行う。
<解説>
一般的なプログラム言語では、< code>タグを発見したら、forループで< p>タグを見つけて、見つかったら削除する。これを< /code>タグに至るまで続ける。
正規表現を使うと、これを5行で実装することができる。
後で変更するのも簡単にできるというのが正規表現を使うメリットと言える。
正規表現で実装するには、次の2段階の手続きをする必要がある。
(1) < code>タグで囲まれた文字列を取得する。
後読み(?<=word)、先読み(?=word)で検索したい文字列の前後の位置を指定する。
後読み、先読みは文字列の先頭(^)、文字列の終端($)と同じ使い方をする。
後読み(?<=word)とは
文字列(word)の終端位置を表す表現。
先読み(?=word)とは
文字列(word)の先頭位置を表す表現。
よって、((\n|.)*?)は< code>タグで囲まれた文字列をあらわすことになる。
(2) その結果をもう一度正規表現を使って検索する。
正規表現に一致した結果をコールバック関数であるfunc_remove_p()に渡して、もう一度正規表現で検索して< p>タグを削除する。
<注意点>
・正規表現で使用するメタ文字とデリミタ文字を文字列指定で使う場合には \(バックスラッシュ)でエスケープする。
メタ文字
(
)
[
]
|
^
$
\
デリミタ文字
/
"
・.は改行を含まないので、(\n|.)とする必要がある。
2023年8月 | ||||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
  |   | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |   |   |
iOS
web
アプリの著作権
ブロックチェーン/暗号技術
新しい社会
禅・大乗仏教
日本のなりたち