[英]RegEx replace returns unexpected result without .*
我正在尝试创建一个执行以下转换的正则表达式:
Apple Orange
> AO
Load Module
> LM
anApple Orange
> O
toLoad Module
> M
我找到了合适的模式,但是注意到了一个奇怪的行为。 这是我最初的尝试:
/^([A-Z])?[^ ]* ([A-Z])/
使用此表达式在第三个(和第四个)测试用例上运行替换操作,得出的结果令人惊讶:
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
为什么这么惊讶? 好了,第一组明显不匹配,因为字符串不以大写字母开头,但第二组只选择一个大写字母: ([AZ])
之后不是一切吧: ([AZ].*)
令我惊讶的是,在最后一个捕获组之后添加.*
给我正确的结果:
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z]).*/,'$1$2')
> "O"
为什么发生这种情况超出了我对JS和正则表达式的理解。 我很高兴知道什么样的黑暗魔法导致单片[AZ]
返回多个,甚至是一些小写字符。
这是一个可运行的演示:
var testCases = [ 'Apple Orange', 'Load Module', 'anApple Orange', 'toLoad Module' ], badregex = /^([AZ])?[^ ]* ([AZ])/, goodregex = /^([AZ])?[^ ]* ([AZ]).*/; 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"
([AZ])?
在开始时检查可选的大写字母。 哪有这回事。 因此它捕获了一个空字符串。 [^ ]*
匹配零个或多个非空格字符。 <space>
匹配一个空格。 ([AZ])
仅捕获Orange的第一个字母。 $1
>空字符串$2
> O
将给您Orange
您的第一个示例与anApple O
匹配。 $1
为空是因为^([AZ])?
是可选的,不匹配和$2
是O
所以你更换anApple O
通过O
在字符串中anApple Orange
,这将导致Orange
除了使用带有复杂正则表达式的replace
,您还可以使用带有match
非常简单的正则表达式,并使用join
获得所需的输出:
'anApple Orange'.match(/\b([A-Z])/g).join('')
//=> O
'Apple Orange'.match(/\b([A-Z])/g).join('')
//=> AO
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.