【JavaScript, 正規表現】ある形式で囲まれたもの以外の文字列を置換する
【実験ページ】
http://usamimi.info/~sutara/sample/regexp_02.html
"てすと"を"test"に置換します。
ただし、class名が"dumy"のタグで囲まれたものは除外します。
例えば下記の文字列を
下記のように変換したい場合。
これはてすと<span class="dumy">てすと</span>てすとですよ<span class="dumy">てすと</span>
これはtest<span class="dumy">てすと</span>testですよ<span class="dumy">てすと</span>
コールバック関数付きのreplaceを使います。
下記は、除外するパターンが明確に決まっている場合の、最も単純な例です。
除外パターンに一致した場合は置換せずにそのまま返し、
var after = before.replace(
/(てすと)|(<span class="dumy">てすと<\/span>)/g,
function() {
if (arguments[2]) {
return arguments[2];
} else if (arguments[1]) {
return 'test';
}
}
);
それ以外に残った"てすと"のみを"test"に置換しています。
次は、かなり複雑です。
class名が"dumy"のタグに囲まれている"てすと"なら、全て除外します。
コールバック関数の部分は変わらないので、正規表現の、
var after = before.replace(
/(てすと)|(<(?:(?!\sclass="|>).)+\sclass="(?:(?:(?!dumy|")\w)+\s)*dumy(?:\s\w+)*"[^>]*>(?:(?!てすと|<).)*てすと[^<]*<\/[^>]+>)/g,
function() {
if (arguments[2]) {
return arguments[2];
} else if (arguments[1]) {
return 'test';
}
}
);
の部分のみを解説します。
<(?:(?!\sclass="|>).)+\sclass="(?:(?:(?!dumy|")\w)+\s)*dumy(?:\s\w+)*"[^>]*>(?:(?!てすと|<).)*てすと[^<]*<\/[^>]+>
前提知識として…、
"\s"は、空白文字です。(\r\n\s\t)
"\w"は、アルファベットと数字とアンダーバーです。([a-zA-Z0-9_])
"(?:"は、"パターンをグループ化したいけど、キャプチャはしたくない"という場合の記法です。
"(?!"は否定先読みです。
【参考】
れぶろぐ - [regexp] ある文字列を含まないものにマッチする正規表現
http://www.revulo.com/blog/20080415.html
では、解説します。
<HTMLタグの始まりにマッチします。以下はタグ内の文字列ということになります。
(?:(?!\sclass="|>).)+『(空白)class="』かHTMLタグの終わり以外の、文字と空白にマッチします。
"h1"や"span"などのタグ名や、他の属性名などを消化することを想定しています。
\sclass="これ以降は、クラス名に対して検査を行います。
(?:(?:(?!dumy|")\w)+\s)*"dumy"まはた『"』ではなく、末尾に空白が付く、
というパターンがあればそれを消化します。
dumy以外のクラス名が併記されている場合を想定しています。
※『class="hoge dumy"』など。
dumy当然、クラス名に"dumy"が含まれていなければなりません。
(?:\s\w+)*その他クラス名が併記されていれば消化します。
※『class="dumy fuga"』など。
"クラス名はここで終了します。
[^>]*HTMLタグ終了まで、他に何か属性名などがあれば消化します。
>HTMLタグはここで終了です。
(?:(?!てすと|<).)*"てすと"またはHTMLタグ開始の記号以外の、文字列があれば消化します。
てすと当然、置換対象の"てすと"は必ず含まれていなければなりません。
[^<]*閉じタグの開始までの文字列を消化します。
<\/閉じタグが始まります。
[^>]+閉じタグが終了するまでの文字列を消化します。
>閉じタグが終了します。
これで、除外パターンの記述が完了しました。