遇到此问题时,我正在浏览正则表达式标记的问题,
需要一个用于网址的正则表达式,该网址以domain.com/advertorials /
开头正则表达式应符合以下情况,
- domain.com/advertorials
- domain.com/advertorials?test=true
- domain.com/advertorials /
domain.com/advertorials/?test=true
但不是这个
domain.com/advertorials/version1?test=true
我想到了此正则表达式advertorials\/?(?:(?!version)(.*))
这应该有效,但在最后一种情况下无效。查看regex101.com中的调试器, 我看到匹配“ s /”后,它逐字符匹配“版本”字词并最终匹配,但是由于这是负向的,因此条件失败。这是我无法理解的部分,因为它无法回溯到“ s /”中的“ /”之前而不是“ s /”之后。
这是应该如何工作的吗?谁能帮我理解? (这是演示链接:https://regex101.com/r/ww3HR8/1)。
谢谢
注意:人们已经对这个问题给出了解决方案,我只想知道为什么我的正则表达式会失败。
答案 0 :(得分:1)
正如您已经指出的,回溯机制负责这种现象。
?
量词(匹配量化子模式的1或0个重复)使正则表达式引擎通过两种方式匹配字符串:要么匹配量化子模式,要么继续将字符串与后续子模式匹配。
因此,advertorials/?(?!version)(.*)
(我删除了冗余的(?:...)
非捕获组),当应用于domain.com/advertorials/version1?test=true
时,先匹配advertorials
,然后再匹配/
,然后,否定的超前查询将检查当前位置右侧是否有version
子字符串。由于version
之后是/
,因此正则表达式引擎返回并看到/?
模式可以匹配空字符串。因此,在advertorials
之后重新应用超前检查。 version
之后没有advertorials
,并返回匹配项。
通常的解决方案是使用所有格量词或原子团,但还有其他方法。
例如
advertorials\/?+(?!version)(.*)
^^
请参见regex demo。在这里,\/?+
匹配1或0个/
字符,但是一旦匹配,egine就不能返回并使用此模式重新匹配字符串的一部分。
或者,您可以将/?
放在前行中,并将其放在/?
模式之前:
advertorials(?!\/?version)\/?(.*)
如果您打算在使用version
之后禁止在任何地方使用advertorials
advertorials(?!.*version)\/?(.*)
请参见yet another demo。
答案 1 :(得分:1)
使斜杠为可选意味着有一种匹配方式而不会违反约束。如果有匹配的方法,则正则表达式引擎将始终找到它。
当斜杠后面紧跟任何东西时,使其为非可选。
function initMap() {
var mapOptions = {
center: new google.maps.LatLng(0, 0),
zoom: 1,
minZoom: 1
};
map = new google.maps.Map(document.getElementById('officeMap'), mapOptions);
google.maps.event.addListenerOnce(map, 'idle', function() {
//Map is ready
worldViewFit(map);
});
}
function worldViewFit(mapObj) {
var worldBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(70.4043,-143.5291), //Top-left
new google.maps.LatLng(-46.11251, 163.4288) //Bottom-right
);
mapObj.fitBounds(worldBounds, 0);
var actualBounds = mapObj.getBounds();
if(actualBounds.getSouthWest().lng() == -180 && actualBounds.getNorthEast().lng() == 180) {
mapObj.setZoom(mapObj.getZoom()+1);
}
}
顺便说一句,正则表达式本身不需要反斜杠转义(尽管某些宿主语言使用斜杠作为正则表达式定界符,所以也许您需要放回斜杠)。我还删除了一些多余的括号。
答案 2 :(得分:0)
原因:
此突出显示的部分是可选的
广告商\/?
(?:( ?! version)(。*))
因此它也可以是advertorials(?:(?!version)(.*))
匹配advertorials/version
本质上,(?!version)(.*)
与/version
匹配
顺便说一句,这是按1个字符进行的正常回溯。
如果您已经修复它,那么我们就完成了!