Javascript 如何将重叠字符串与正则表达式匹配?
假设我有绳子Javascript 如何将重叠字符串与正则表达式匹配?,javascript,regex,Javascript,Regex,假设我有绳子 "12345" 如果我.match(/\d{3}/g),我只得到一个匹配项,“123”。为什么我得不到[“123”、“234”、“345”]?当表达式匹配时,它通常使用匹配的字符。因此,在表达式匹配123之后,只剩下45,这与模式不匹配。当表达式匹配时,它通常使用匹配的字符。因此,在表达式匹配123后,只剩下45,这与模式不匹配。要回答“如何”,可以手动更改最后一个匹配的索引(需要循环): 为了方便起见,这里有一个函数: function matchOverlap(input,
"12345"
如果我
.match(/\d{3}/g)
,我只得到一个匹配项,“123”
。为什么我得不到[“123”、“234”、“345”]
?当表达式匹配时,它通常使用匹配的字符。因此,在表达式匹配123
之后,只剩下45
,这与模式不匹配。当表达式匹配时,它通常使用匹配的字符。因此,在表达式匹配123
后,只剩下45
,这与模式不匹配。要回答“如何”,可以手动更改最后一个匹配的索引(需要循环):
为了方便起见,这里有一个函数:
function matchOverlap(input, re) {
var r = [], m;
// prevent infinite loops
if (!re.global) re = new RegExp(
re.source, (re+'').split('/').pop() + 'g'
);
while (m = re.exec(input)) {
re.lastIndex -= m[0].length - 1;
r.push(m[0]);
}
return r;
}
用法示例:
matchOverlap('12345', /\D{3}/) // []
matchOverlap('12345', /\d{3}/) // ["123", "234", "345"]
matchOverlap('12345', /\d{3}/g) // ["123", "234", "345"]
matchOverlap('1234 5678', /\d{3}/) // ["123", "234", "567", "678"]
matchOverlap('LOLOL', /lol/) // []
matchOverlap('LOLOL', /lol/i) // ["LOL", "LOL"]
要回答“如何”,您可以手动更改最后一个匹配的索引(需要循环):
为了方便起见,这里有一个函数:
function matchOverlap(input, re) {
var r = [], m;
// prevent infinite loops
if (!re.global) re = new RegExp(
re.source, (re+'').split('/').pop() + 'g'
);
while (m = re.exec(input)) {
re.lastIndex -= m[0].length - 1;
r.push(m[0]);
}
return r;
}
用法示例:
matchOverlap('12345', /\D{3}/) // []
matchOverlap('12345', /\d{3}/) // ["123", "234", "345"]
matchOverlap('12345', /\d{3}/g) // ["123", "234", "345"]
matchOverlap('1234 5678', /\d{3}/) // ["123", "234", "567", "678"]
matchOverlap('LOLOL', /lol/) // []
matchOverlap('LOLOL', /lol/i) // ["LOL", "LOL"]
单用正则表达式无法做到这一点,但可以非常接近:
var pat=/(?=(\d{3}))\d/g;
var结果=[];
var匹配;
while((match=pat.exec('1234567'))!=null){
结果:推(匹配[1]);
}
控制台日志(结果)代码>单用正则表达式无法做到这一点,但可以非常接近:
var pat=/(?=(\d{3}))\d/g;
var结果=[];
var匹配;
while((match=pat.exec('1234567'))!=null){
结果:推(匹配[1]);
}
控制台日志(结果)
带有全局标志regex的字符串#match
返回匹配的子字符串数组。/\d{3}/g
正则表达式匹配并使用(=读入缓冲区并将其索引前进到当前匹配字符后面的位置)3位序列。因此,在“吃掉”123
之后,索引位于3
之后,唯一剩下的用于解析的子字符串是45
——此处不匹配
我认为在中使用的技术也值得考虑:使用零宽度断言(捕获组的正向前瞻)来测试输入字符串中的所有位置。在每次测试之后,“手动”推进(它是正则表达式的读/写整数属性,指定开始下一次匹配的索引)以避免无限循环
注意,它是一种在.NET(Regex.Matches
)、Python(re.findall
)、PHP(preg\u match\u all
)、Ruby(String#scan
)中实现的技术,也可以在Java中使用。
下面是一个使用matchAll
的演示:
var re=/(?=(\d{3}))/g;
log(Array.from('12345'.matchAll(re),x=>x[1])
带有全局标志regex的字符串#match
返回匹配的子字符串数组。/\d{3}/g
正则表达式匹配并使用(=读入缓冲区并将其索引前进到当前匹配字符后面的位置)3位序列。因此,在“吃掉”123
之后,索引位于3
之后,唯一剩下的用于解析的子字符串是45
——此处不匹配
我认为在中使用的技术也值得考虑:使用零宽度断言(捕获组的正向前瞻)来测试输入字符串中的所有位置。在每次测试之后,“手动”推进(它是正则表达式的读/写整数属性,指定开始下一次匹配的索引)以避免无限循环
注意,它是一种在.NET(Regex.Matches
)、Python(re.findall
)、PHP(preg\u match\u all
)、Ruby(String#scan
)中实现的技术,也可以在Java中使用。
下面是一个使用matchAll
的演示:
var re=/(?=(\d{3}))/g;
log(Array.from('12345'.matchAll(re),x=>x[1])代码>使用(?=(\w{3}))
(3是序列中的字母数)使用(?=(\w{3}))
(3是序列中的字母数)
,我会考虑不使用正则表达式。如果要分成三组,可以从偏移量开始在字符串上循环:
s=“12345”
设m=Array.from(s.slice(2),(u,i)=>s.slice(i,i+3))
控制台。log(m)< /c> > p>我会考虑不使用正则表达式。如果要分成三组,可以从偏移量开始在字符串上循环:
s=“12345”
设m=Array.from(s.slice(2),(u,i)=>s.slice(i,i+3))
console.log(m)
您只获得一个匹配项,因为“123”
已匹配,而剩余字符“45”
不匹配。如果您使用/\d{2}/g
,您将得到['12','34']
。无论如何,在SO中有一个答案,即使它们重叠,也可以获得匹配字符串:您只获得一个匹配,因为“123”
已经匹配,而剩余的字符“45”
不匹配。如果您使用/\d{2}/g
,您将得到['12','34']
。无论如何,在中有一个答案,即使它们重叠也可以得到匹配的字符串:因为while循环的条件永远不会改变,所以源代码会产生一个无止境的循环。。。正如@Wiktor Stribiżew在他的回答中已经提到的,必须更改regex对象的索引才能更改匹配结果。由于while循环的条件从未改变,因此源代码产生了一个无止境的循环。。。正如@Wiktor Stribiżew在他的回答中已经提到的,必须更改regex对象的索引才能更改匹配结果。哦,是的,谢谢你的提示!删除了相关评论:“我认为在最后一个源代码块中有一个小错误:不是res.push(m[0]);必须使用res.push(m[1]);因为匹配结果存储在数组m的索引1而不是索引0中”哦,是的,谢谢你的提示!删除了相关评论:“我认为这只是一个