次の変換を行う正規表現を作成しようとしています。
Apple Orange
>AO
Load Module
>LM
anApple Orange
>O
toLoad Module
>M
適切なパターンを見つけましたが、奇妙な動作に気付きました。これが私の最初の試みです:
/^([A-Z])?[^ ]* ([A-Z])/
この式で 3 番目 (および 4 番目) のテスト ケースで置換を実行すると、驚くべき結果が得られます。
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
なぜそれは驚くべきことですか?文字列が大文字で始まっていないため、最初のグループは明らかに一致しませんが、2 番目のグループは単一の大文字のみを選択します: ([A-Z])
、その後のすべてではありません:([A-Z].*)
驚いたことに、.*
最後のキャプチャ グループの直後に追加すると、正しい結果が得られました。
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z]).*/,'$1$2')
> "O"
なぜこれが起こっているのかは、JS と正規表現についての私の理解を超えています。どのような種類の闇の魔法が単一の文字[A-Z]
を複数の文字や小文字の文字でさえも返すのかを知ることに興奮しています。
実行可能なデモは次のとおりです。
var testCases = [
'Apple Orange',
'Load Module',
'anApple Orange',
'toLoad Module'
],
badregex = /^([A-Z])?[^ ]* ([A-Z])/,
goodregex = /^([A-Z])?[^ ]* ([A-Z]).*/;
document.onreadystatechange = function(n){
if (document.readyState === "complete"){
for (var i=0,l=testCases.length; i<l; i++){
var p = document.createElement('p'),
testCase = testCases[i];
p.innerHTML = ""+testCase+" > "+testCase.replace(badregex,'$1$2')
document.body.appendChild(p);
}
document.body.appendChild(document.createElement('hr'));
for (var i=0,l=testCases.length; i<l; i++){
var p = document.createElement('p'),
testCase = testCases[i];
p.innerHTML = ""+testCase+" > "+testCase.replace(goodregex,'$1$2')
document.body.appendChild(p);
}
}
}