我正在尝试创建一个执行以下转换的正则表达式:
苹果橙
>AO
加载模块
>LM
一个苹果橙
>O
加载模块
>M
我找到了合适的模式,但发现了一个奇怪的行为。这是我的初步尝试:
/^([A-Z])?[^ ]* ([A-Z])/
用这个表达式对第三个(和第四个)测试用例运行替换给了我一个令人惊讶的结果:
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
为什么令人惊讶?好吧,第一组显然不匹配,因为字符串不是以大写字母开头,但第二组只选择了一个单个大写字母:([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);
}
}
}
最佳答案
我愿意,
> "Apple Orange".replace(/(?:^|\s)([A-Z])|./g, "$1")
'AO'
不要把事情复杂化。只需捕获紧随空格或开头的所有大写字符即可。然后匹配所有剩余的字符。现在将所有匹配的字符替换为 $1
.请注意,所有匹配的字符都将替换为替换部分中存在的字符。
为什么?
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
-
([A-Z])?
在开头检查可选的大写字母。哪有这回事。所以它捕获一个空字符串。 -
[^ ]*
匹配零个或多个非空格字符。 -
<space>
匹配一个空格。 -
([A-Z])
仅捕获 Orange 中的第一个字母。 - 现在用
$1
替换所有匹配的字符-> 空字符串$2
->O
会给你Orange
关于javascript - RegEx 替换返回意外结果,没有 .*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30740465/