首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

正则表达式 一个奇怪问题

  •  
  •   faketemp · 24 天前 · 1079 次点击

    测试工具: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”吗

    百思不得其解中……

    22 回复  |  直到 2019-10-22 11:57:59 +08:00
        1
    faketemp   24 天前 via iPhone
    以前未遇到过这种奇怪问题 测试多个编辑器 结果都是一样 实在是费解
        2
    shiji   24 天前
    .+? 。*? 是 Lazy。
    懒惰的意思是,尽量少的匹配(不贪婪)直到满足条件。

    那么最前面的 http 是满足条件的,regex 里面的 http 也会相应的“划掉”,在到达终点 MAIN 之前,不管贪婪还是懒惰,中间的都得包含进去,没得选。

    (中途因为 http 已经匹配上了,再次看到 http 的时候 regex 会忽略,反正已经匹配了。)

    所以 Lazy 不能保证最短。。。
        3
    faketemp   24 天前 via iPhone
    @shiji 看各种教程都说?符号是“最短匹配” 如果 lazy 不能保证最短 请问像上面需求如何才能匹配出所要的“最短匹配”结果呢(假设网址部分是不定长的)
        4
    faketemp   24 天前 via iPhone
    @shiji 能够理解你的讲解 要查找出“最短匹配”结果 想到一种折中方案 就是先将文本逆序 正则匹配出结果后再逆序一次 😁这种方案好像很笨……
        5
    lxk11153   24 天前   ♥ 1
    中间部分是.+?匹配中的。你可以试试断言来排除中间的 ht 河蟹 tp
    htt 河蟹 ps://blog.csdn.ne 河蟹 t/u01204 河蟹 7933/article/details/383 河蟹 65541
        6
    shiji   24 天前   ♥ 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   24 天前 via Android   ♥ 1
    因为正则都是从前向后的吧
    第一个 http 符合要求就开始匹配,然后才是.+?main 的最短
        8
    lukaz   24 天前   ♥ 1
    针对测试文本,假设网址部分不含逗号,那么可以这样: http[^,]+,MAIN
        9
    faketemp   24 天前 via iPhone
    受以上指导启发 只能这样了 使用

    http((?!http).)+?MAIN
    或者
    http[^http]+?MAIN
        10
    faketemp   24 天前 via iPhone
    @pkookp8 嗯 我甚至专门去查过 有什么正则支持逆序查找选项🤪
        11
    lukaz   24 天前 via Android   ♥ 1
    [^http]的意思不是想当然的[^( http)],不能这么用
        12
    geelaw   24 天前 via iPhone   ♥ 1
    Lazy 模式并不是 skip 模式。
    你的需求可以用一个 NFA 解决,基本思路是匹配 http,以及一坨不含 http 和 ,MAIN 的串,以及 ,MAIN。见 https://www.v2ex.com/t/602716
        13
    faketemp   24 天前 via iPhone
    @lukaz 谢谢提示 深入测试一下确实如你所说 这种用法是不准确的
    所以目前来看 就只能使用零宽断言 http((?!http).)+?MAIN
    或者逆序后 lazy 模式查找

    @geelaw 理论能够理解 只是最终结果没看懂🤪
        14
    noqwerty   24 天前 via Android   ♥ 1
    以前一直觉得自己写正则还可以,在 V2 看了几个帖子之后感觉自己真的菜
        15
    toma77   23 天前
    我最讨厌正则
        16
    ClericPy   23 天前
    昨天就看到这帖子, 然后...
    测试工具:Notepad++
    劝退了
        17
    faketemp   23 天前
    @ClericPy 技术无关 zz

    师夷长技以制夷

    用 sublimetext 或者 emeditor 等测试 问题一样重现 个人习惯
        18
    ClericPy   23 天前
    @faketemp 太敏感了...
    本来以为是聊正则的, 结果... 这软件我没装, 不知道会是什么效果, 不来坑楼主
        19
    ClericPy   23 天前   ♥ 1
    又看了下那些回帖, 已经有答案了, 这个条件改用零宽断言是对的 http(?:(?!http).)+?MAIN
    被测试工具四个字给误导了, 以为是上来问 notepad++ 软件问题

    提个小建议, 以后跨工具测试正则可以 https://regex101.com/ 省的一个个工具去安装了
        20
    faketemp   23 天前
    @ClericPy 感谢关注

    目前收集到的几个正则 实测都可以准确查找
    分别为
    http(?:(?!http).)+?MAIN
    http:((?<!MAIN|http).)+?MAIN
    http((?!http).)+?MAIN

    记录一下给需要的 V 友学习哈
        21
    ClericPy   23 天前
    @faketemp
    呃, 这和 NFA 引擎不会做那些细致回溯有点关系, 可以参考用 aa 匹配 aaaa 会发现只会得到两个结果, 而不是三个结果, 基本上就是拿着正则串去原始字符串里找, 具体算法还挺有意思, 可以去了解下 NFA 和 DFA 方面的东西
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3005 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 24ms · UTC 00:58 · PVG 08:58 · LAX 16:58 · JFK 19:58
    ♥ Do have faith in what you're doing.