正则表达式 后面不要包含内容 的写法不生效? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
xiangyuecn
V2EX    程序员

正则表达式 后面不要包含内容 的写法不生效?

  •  
  •   xiangyuecn
    xiangyuecn 2019-04-08 08:09:39 +08:00 3685 次点击
    这是一个创建于 2429 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天学会了如何编写 不要包含指定的字符串内容 的正则表达式写法。

    特意写了一篇文章记录了一下:

    https://www.cnblogs.com/xiangyuecn/p/10668378.html

    里面有一个一直困扰的问题,假设:

    提取<abcdef>\n<abczzz>中首个不包含 def 结尾的 abc 标签,只知道def,不知道zzz


    很简单能写成( v2 页面浏览器控制台测试,但 not only Javascript ):

    /<abc(?!def).+>/.exec("<abcdef>\n<abczzz>")


    但往往我们不能写死abc,顺理成章的就写成了:

    /<.+(?!def).+>/.exec("<abcdef>\n<abczzz>")


    上面这个不生效,昨天刚发现写成这样就可以了:

    /<(?:.(?!def))+>/.exec("<abcdef>\n<abczzz>")


    不明白为什么.+(?!def)不会生效,前瞻不会和前面的+、*、{}起作用吗?

    第 1 条附言    2019-04-08 09:38:01 +08:00

    由于/<.+(?!def).+>/ 结尾还有一个贪婪匹配(虽然实际上只会匹配到结尾仅仅一个字符,看上去像是会匹配所有字符一样,不测试好难看出是哪个.+匹配出来的),这个例子不太好。

    换成#1楼这个例子吧,没这么多干扰:

    /<.+(?!def)zzz>/.exec("<abcdefzzz>\n<abczzz>")

    另注:这里所写的语法,js应该都支持的吧。

    xiangyuecn
        1
    xiangyuecn  
    OP
       2019-04-08 08:24:35 +08:00
    又发现另一种有效写法:
    /<(?!.+def).+>/.exec("<abcdefzzz>\n<abczzz>")

    可能是结尾的.+导致的不能匹配,但这样写还是不行:
    /<.+(?!def)zzz>/.exec("<abcdefzzz>\n<abczzz>")
    frank611
        2
    frank611  
       2019-04-08 08:26:55 +08:00 via Android
    def 后面的.+是不对的,+是必须匹配一个字符或者更多
    binux
        3
    binux  
       2019-04-08 08:27:32 +08:00
    /<(.+)(?!def)(.+)>/.exec("<abcdef>\n<abczzz>")
    你就知道为什么了
    xiangyuecn
        4
    xiangyuecn  
    OP
       2019-04-08 08:31:39 +08:00
    @binux 还是不明白,第一个分组捕获到 abcde,预期想要是 abc,前瞻不会和前面的+、*、{}起作用吗?
    binux
        5
    binux  
       2019-04-08 08:36:41 +08:00   1
    @
    zhyl
        6
    zhyl  
       2019-04-08 08:36:53 +08:00 via Android   1
    .+ 贪婪匹配
    labnotok
        7
    labnotok  
       2019-04-08 09:23:20 +08:00 via Android
    貌似 js 不支持预查吧,只能手动分组
    xiangyuecn
        8
    xiangyuecn  
    OP
       2019-04-08 09:27:46 +08:00
    @binux 还是不太明白,第一个分组的确是捕获到了`abcde`呀,

    照着你的思路找到 https://developer.mozilla.org/en-US/docs/Web/Javascript/Guide/Regular_Expressions 的解释中有个例子:
    > >>>>>
    Matches 'x' only if 'x' is not followed by 'y'. This is called a negated lookahead.

    For example, /\d+(?!\.)/ matches a number only if it is not followed by a decimal point. The regular expression /\d+(?!\.)/.exec("3.141") matches '141' but not '3.141'.
    > >>>>>

    发现一个现象:

    符合预期:/(\d+)(?!\.1)/.exec("123.141")
    符合预期:/([^.]+)(?!\.1)/.exec("123.141")
    无效:/(.+)(?!\.1)/.exec("123.141")

    难以理解,最后一个就是我的写法,咳。。。
    araraloren
        9
    araraloren  
       2019-04-08 09:29:27 +08:00
    js 的正则有些特性不支持: https://www.regular-expressions.info/Javascript.html
    xiangyuecn
        10
    xiangyuecn  
    OP
       2019-04-08 09:30:37 +08:00
    noqwerty
        11
    noqwerty  
       2019-04-08 09:37:16 +08:00   1
    你这个非要用正则的话感觉只能 <(?!.+def>).+> ,你的写法里 <.+(?!def).+> 第一个.+是贪婪的,会把 def 也包括进去。
    noqwerty
        12
    noqwerty  
       2019-04-08 09:38:06 +08:00
    另外测试正则的时候 https://regex101.com/ 很好用
    binux
        13
    binux  
       2019-04-08 09:38:16 +08:00   1
    @xiangyuecn #8
    /<.+(?!def).+>/.exec("<abcdef>\n<abczzz>")
    第一个 .+ 匹配到了 abcde,之后是 f,不是 def,第二个 .+ 匹配 f,符合正则

    /(.+)(?!\.1)/.exec("123.141")
    第一个 .+ 匹配到了 123.141 ,之后是 EOF 不是 .1,也符合正则
    xiangyuecn
        14
    xiangyuecn  
    OP
       2019-04-08 10:08:46 +08:00
    @binux 嗯,原来如此呀,分解一下豁然开朗,哈哈

    意思就是前瞻只能作用于+贪婪匹配到的最后一个字符,并不能阻止+对最后一个字符之前的所有字符进行贪婪匹配。

    /(\d+)(?!\.1)/.exec("123.141") 目测是这样的:
    > 123:\d+贪婪匹配到.为止
    > 12:发现 123.1 不符合(?!\.1),后退一位
    > 没有表达式了,返回 12

    /(.+)(?!\.1)/.exec("123.141") 目测是这样的:
    > 123.141:.+贪婪匹配到结尾
    > 123.141 : 符合(?!\.1)
    > 没有表达式了,返回 123.141

    /(.(?!\.1))+/.exec("123.141") 目测是这样的:
    > 1:.匹配到新的一位
    > 1:123 符合(?!\.1)
    > 12:.匹配到新的一位
    > 12:123.符合(?!\.1)
    > 123:.匹配到新的一位
    > 12:发现 123.1 不符合(?!\.1),后退一位,并退出循环
    > 没有表达式了,返回 12

    如果要对每个字符进行前瞻检查,唯有最后一种写法比较好理解。
    zhyl
        15
    zhyl  
       2019-04-08 11:03:55 +08:00
    试试这个 `<\w+(?!def)(?<!def)\b>`
    xiangyuecn
        16
    xiangyuecn  
    OP
       2019-04-08 11:05:53 +08:00
    @zhyl 尽量不要用后瞻,难移植
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3828 人在线   span class="fade">最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 00:59 PVG 08:59 LAX 16:59 JFK 19:59
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86