String.replace の第二引数には置換関数を指定できる

String.replace の第二引数には、置換後の文字列を返す、独自の関数を指定できることを知った。目的にもよるが、グルーピングを使うときは RegExp.exec を繰り返すよりも使いやすい。

ただし、置換関数に渡される引数が可変で、いくらか複雑なので注意が必要。

以下、ActionSript 3.0 での例。

var str:String = "aaaA bbbB cccC";
str = str.replace(/([a-z]+)([A-Z])/g, function():String {
trace(arguments);
return arguments[1].toUpperCase() + arguments[2].toLowerCase();
});
trace(str);
===========================
aaaA,aaa,A,0,aaaA bbbB cccC
bbbB,bbb,B,5,aaaA bbbB cccC
cccC,ccc,C,10,aaaA bbbB cccC
AAAa BBBb CCCc

global フラグが立っているので、3 箇所のマッチ全てに対して置換関数が実行される。

この場合の引数の各要素は、

第一引数
([a-z]+)([A-Z]) にマッチする文字列
第二引数
([a-z]+) にマッチする文字列
第三引数
([A-Z]) にマッチする文字列
第四引数
([a-z]+)([A-Z]) にマッチする文字列の位置
第五引数
replace を実行する文字列

となる。

Ecma-262.pdf の 15.5.4.11 項を引用しておく。

If replaceValue is a function, then for each matched substring, call the function with the following m + 3 arguments. Argument 1 is the substring that matched. If searchValue is a regular expression, the next m arguments are all of the captures in the MatchResult (see 15.10.2.1). Argument m + 2 is the offset within string where the match occurred, and argument m + 3 is string. The result is a string value derived from the original input by replacing each matched substring with the corresponding return value of the function call, converted to a string if need be.