2010年12月6日月曜日

JavaScriptで、タグの外側だけを置換する。

例えば、
<p>あいうえおAAAかきくけこbbbさしすせそCCC<br/>たたたDDDちちちeeeつつつFFFてててててgとととと</p>
というhtmlがあった場合に、これの英字の部分だけを太字にしようとしたとする。
だけれど素直に
var html="<p>あいうえおAAAかきくけこbbbさしすせそCCC<br/>たたたDDDちちちeeeつつつFFFてててててgとととと</p>";
html=html.replace(/(\w+)/g,"<b>$1</b>");
などとやると、
<<b>p</b>>あいうえお<b>AAA</b>かきくけこ<b>bbb</b>さしすせそ<b>CCC</b><<b>br</b>/>たたた<b>DDD</b>ちちち<b>eee</b>つつつ<b>FFF</b>ててててて<b>g</b>とととと</<b>p</b>>
のようにタグ内の文字まで置換されてしまうわけで……。

そこで、タグの外を置換する正規表現を調べると、やたらと難しい正規表現を書かなきゃいけない。自分は正規表現はわりと得意な方だと思ってるけれど、それでもかなり理解に苦しむ。書いてみても動かない。
だいたい、タグ自体にマッチさせる正規表現は、ちょっと勉強すれば誰でもわかる。<[^>]*?>だ。

ピンと来た!
var html="<p>あいうえおAAAかきくけこbbbさしすせそCCC<br/>たたたDDDちちちeeeつつつFFFてててててgとととと</p>";

html=html.replace(/<[^>]*?>|(\w+)/g,
function(s0,s1){
if(s1===undefined) return s0;
return '<b>'+s1+'</b>';
});
<p>あいうえお<b>AAA</b>かきくけこ<b>bbb</b>さしすせそ<b>CCC</b><br/>たたた<b>DDD</b>ちちち<b>eee</b>つつつ<b>FFF</b>ててててて<b>g</b>とととと</p>

これでいい。正規表現内では先にタグをひっかけ、キャプチャがなければ全体をそのまま返す。
タグになった部分の文字は見なくなるから、あとはキャプチャ文字にbタグをかけて返せばいい。
これかなり応用がききそう!


ついでに、Groovyならばこう。
String html="<p>あいうえおAAAかきくけこbbbさしすせそCCC<br/>たたたDDDちちちeeeつつつFFFてててててgとととと</p>";

html=html.replaceAll(/<[^>]*?>|(\w+)/){s0,s1->
if(s1==null) return s0
return "<b>$s1</b>";
}

println html


2010.12.8追記:
タグ外だけ置換を連続でやるならつまり、こういうこと。
var html="<p style=\"color:red;\">あいうえおpAAAかきくけこ<br/>bbbさしすせそCCC</p>\
<p>たたたDDDちちちpeeeつつつF<br/>FFてててててgとととと</p>";

function replaceOutsideTags(str,reg,rep){
return str.replace(/<[^>]*?>|([^<]+)/g,
function(s0,s1){return (s1===undefined)?s0:s1.replace(reg,rep);
});
};

html = replaceOutsideTags(html,/(\w+)/g,"<b>$1</b>");
html = replaceOutsideTags(html,/p/g,"ぴぃ");
html = replaceOutsideTags(html,/b/g,"火");
html = replaceOutsideTags(html,/ち/g,"血");
$.writeln(html);

0 件のコメント: