测试工具:Notepad++
测试文本: http://www.baidu.com,http://www.123.com,http://www.sina.com,MAIN
测试正则: http.+?MAIN
测试结果: http://www.baidu.com,http://www.123.com,http://www.sina.com,MAIN
问题是非贪婪模式下最短匹配,结果不应该是“http://www.sina.com,MAIN”吗
百思不得其解中……
1
faketemp OP 以前未遇到过这种奇怪问题 测试多个编辑器 结果都是一样 实在是费解
|
2
shiji 2019-10-21 22:58:24 +08:00
.+? 。*? 是 Lazy。
懒惰的意思是,尽量少的匹配(不贪婪)直到满足条件。 那么最前面的 http 是满足条件的,regex 里面的 http 也会相应的“划掉”,在到达终点 MAIN 之前,不管贪婪还是懒惰,中间的都得包含进去,没得选。 (中途因为 http 已经匹配上了,再次看到 http 的时候 regex 会忽略,反正已经匹配了。) 所以 Lazy 不能保证最短。。。 |
3
faketemp OP @shiji 看各种教程都说?符号是“最短匹配” 如果 lazy 不能保证最短 请问像上面需求如何才能匹配出所要的“最短匹配”结果呢(假设网址部分是不定长的)
|
4
faketemp OP @shiji 能够理解你的讲解 要查找出“最短匹配”结果 想到一种折中方案 就是先将文本逆序 正则匹配出结果后再逆序一次 😁这种方案好像很笨……
|
5
lxk11153 2019-10-21 23:31:45 +08:00 1
中间部分是.+?匹配中的。你可以试试断言来排除中间的 ht 河蟹 tp
htt 河蟹 ps://blog.csdn.ne 河蟹 t/u01204 河蟹 7933/article/details/383 河蟹 65541 |
6
shiji 2019-10-22 00:15:27 +08:00 1
@faketemp 逆序其实不笨,并且很有效率。。
设想这样一个字符串 http://www.du.com,MAIN,http://www.123.com,http://www.sina.com,MAIN,http://www.baidu.com,MAIN,http://www.123.com,MAIN 你期望的输出是什么? 如果不逆过来, 试试 ( http:((?<!MAIN|http).)*MAIN) 然后跑代码找出最短的 |
7
pkookp8 2019-10-22 00:29:29 +08:00 via Android 1
因为正则都是从前向后的吧
第一个 http 符合要求就开始匹配,然后才是.+?main 的最短 |
8
lukaz 2019-10-22 00:30:52 +08:00 1
针对测试文本,假设网址部分不含逗号,那么可以这样: http[^,]+,MAIN
|
9
faketemp OP 受以上指导启发 只能这样了 使用
http((?!http).)+?MAIN 或者 http[^http]+?MAIN |
11
lukaz 2019-10-22 00:44:16 +08:00 via Android 1
[^http]的意思不是想当然的[^( http)],不能这么用
|
12
geelaw 2019-10-22 04:17:26 +08:00 via iPhone 1
Lazy 模式并不是 skip 模式。
你的需求可以用一个 NFA 解决,基本思路是匹配 http,以及一坨不含 http 和 ,MAIN 的串,以及 ,MAIN。见 https://www.v2ex.com/t/602716 |
13
faketemp OP |
14
noqwerty 2019-10-22 07:36:16 +08:00 via Android 1
以前一直觉得自己写正则还可以,在 V2 看了几个帖子之后感觉自己真的菜
|
15
toma77 2019-10-22 09:59:39 +08:00
我最讨厌正则
|
16
ClericPy 2019-10-22 11:14:32 +08:00
昨天就看到这帖子, 然后...
测试工具:Notepad++ 劝退了 |
17
faketemp OP |
19
ClericPy 2019-10-22 11:36:16 +08:00 1
又看了下那些回帖, 已经有答案了, 这个条件改用零宽断言是对的 http(?:(?!http).)+?MAIN
被测试工具四个字给误导了, 以为是上来问 notepad++ 软件问题 提个小建议, 以后跨工具测试正则可以 https://regex101.com/ 省的一个个工具去安装了 |
20
faketemp OP @ClericPy 感谢关注
目前收集到的几个正则 实测都可以准确查找 分别为 http(?:(?!http).)+?MAIN http:((?<!MAIN|http).)+?MAIN http((?!http).)+?MAIN 记录一下给需要的 V 友学习哈 |
21
ClericPy 2019-10-22 11:50:32 +08:00
@faketemp
呃, 这和 NFA 引擎不会做那些细致回溯有点关系, 可以参考用 aa 匹配 aaaa 会发现只会得到两个结果, 而不是三个结果, 基本上就是拿着正则串去原始字符串里找, 具体算法还挺有意思, 可以去了解下 NFA 和 DFA 方面的东西 |
22
faketemp OP |