V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jurassic2long
V2EX  ›  程序员

你有一个问题,决定使用正则解决,现在你有两个问题了?!

  •  
  •   jurassic2long · 2022-08-29 10:13:00 +08:00 · 5511 次点击
    这是一个创建于 817 天前的主题,其中的信息可能已经有所发展或是发生改变。

    工作多年,每次使用正则表达式都要测试好几次才敢用。 大家来分享一下自己使用正则的技巧, 或者分享遇到的大坑,让大家乐呵乐呵~

    37 条回复    2022-08-31 10:28:12 +08:00
    BingoXuan
        1
    BingoXuan  
       2022-08-29 10:17:15 +08:00
    复杂的匹配都是先匹配一次,把匹配结果再进行匹配
    seers
        2
    seers  
       2022-08-29 10:17:43 +08:00 via Android
    我能用逻辑判断的还是避免写正则,有时候自己写的过两个月自己都看不懂
    murmur
        3
    murmur  
       2022-08-29 10:17:57 +08:00
    能用库尽量用库,比如 html 标签过滤这些,有的时候正则写复杂需求就是想 shi
    Kasumi20
        4
    Kasumi20  
       2022-08-29 10:24:07 +08:00
    具体说说这个问题,我很好奇怎么变成两个问题的
    loading
        5
    loading  
       2022-08-29 10:25:37 +08:00
    除非有极致的性能要求(正则也不见得比很多 if 要快),或者非常简单或常见的情况,不然我一般不会用正则。

    因为我还会遇到另外两个问题:
    1.太久没用又要学一次,doge 。
    2.没写注释,看不懂了。
    lixinrui000
        6
    lixinrui000  
       2022-08-29 10:27:18 +08:00   ❤️ 2
    我一般用 regex101 测试好再贴到代码里
    jurassic2long
        7
    jurassic2long  
    OP
       2022-08-29 10:31:30 +08:00
    @Kasumi20 第二个问题是:怎么用正则表示第一个问题。


    @loading 太真实了,用一次学一次。


    @seers
    @murmur 我的需求一般是字符串格式判断和提取,最近一次忘了写非贪婪匹配的? 就悲剧了
    gromit1337
        8
    gromit1337  
       2022-08-29 10:45:29 +08:00
    nuk
        9
    nuk  
       2022-08-29 12:02:26 +08:00
    正则主要就字符串匹配和捕捉,复杂一点的就用 lpeg ,好用到飞起。
    devswork
        10
    devswork  
       2022-08-29 12:28:41 +08:00   ❤️ 1
    https://regexper.com/ 用这个,正则表达式图形化
    Natumsol
        11
    Natumsol  
       2022-08-29 12:47:55 +08:00
    HankAviator
        12
    HankAviator  
       2022-08-29 12:51:01 +08:00 via Android
    @loading 正则不是效率比较差吗
    Cat7373
        13
    Cat7373  
       2022-08-29 12:54:55 +08:00
    正则很容易的🐶
    imn1
        14
    imn1  
       2022-08-29 13:08:45 +08:00
    我发觉很多时候给别人答案是正则时,对方甚少接受的
    正则我很常用,因为平常文件改名、搜索文件、搜索文本……就在用,最小的频率也不低于 1 次 /2 天,所以大部分都能读懂和手写


    @HankAviator #12
    跟纯 string 函数比,是效率低,但也是次数少的情况,但其他场景就不一定了
    1. 要好几个甚至非常多字符串函数组合的情况
    2. 需要泛匹配的情况
    3. 数量巨大,例如十万或百万 html 匹配,用正则比 DOM 效率高很多
    ikaros
        15
    ikaros  
       2022-08-29 14:56:46 +08:00
    能不用就不用, 每次都要重新去看一下语法, 然后过几天又忘了
    herozzm
        16
    herozzm  
       2022-08-29 14:57:41 +08:00   ❤️ 1
    regex101 是神器,测试通过就可用了
    zifangsky
        17
    zifangsky  
       2022-08-29 15:52:29 +08:00
    写完之后在文本编辑器中多测试一下不同场景( PS:现在主流的文本编辑器基本都可以测试正则表达式匹配),基本就没啥问题了
    Jooooooooo
        18
    Jooooooooo  
       2022-08-29 15:53:39 +08:00
    你想写一个匹配邮箱的正则, 结果发现茫茫多的边缘 case

    比如 1@1 是合法的邮箱吗?
    HikariLan
        19
    HikariLan  
       2022-08-29 15:55:16 +08:00 via Android
    @lixinrui000 regex101 是我个人觉得最好的正则表达式解析网站了
    bulay
        20
    bulay  
       2022-08-29 17:03:29 +08:00
    写正则到还好吧.最坑的是遇见过正则死循环.程序跑半天不结束,cpu 跑满.
    具体原因也不知道为啥,去掉 * 号重写就好了
    fstar
        21
    fstar  
       2022-08-29 17:52:05 +08:00
    正则简单的还好,复杂的头晕,可能还有潜藏的 case 没有覆盖以及性能问题

    个人认为能不用就不用。

    骚操作:读到 `<div class="member">用户名</div>`,用 string.repace(/^<div class="member">(.*)</div>$/, $0) 提取用户名。
    libook
        22
    libook  
       2022-08-29 17:59:45 +08:00
    测试覆盖好边界,注释写清楚。
    yjhatfdu2
        23
    yjhatfdu2  
       2022-08-29 18:34:00 +08:00
    更复杂的场景写 parser
    Terry05
        24
    Terry05  
       2022-08-29 19:04:36 +08:00
    正则这东西真特么神奇,隔一段时间绝对可以忘得一干二净!
    zlowly
        25
    zlowly  
       2022-08-29 20:32:07 +08:00
    正则这东西,真是只有在所有可以使用的正则的地方经常使用,才能体现投入产出比。
    但是麻烦的就是在 php,python,grep,vim,sed 各类可以使用的地方,他们的正则在细微处总有差异,特别在转义方面有着各自的坚持,实在是令人抓狂。
    zlowly
        26
    zlowly  
       2022-08-29 20:35:43 +08:00
    除了上面提到的 regex101.com ,补充个 debuggex.com 的图形化显示也能较好辅助理解。
    wxf666
        27
    wxf666  
       2022-08-29 23:22:34 +08:00
    @bulay 你这是遇到“灾难性回溯”(或“回溯陷阱”)了

    随便一搜,资料很多。比如: https://zh.javascript.info/regexp-catastrophic-backtracking
    liuxu
        28
    liuxu  
       2022-08-30 00:29:25 +08:00
    @fstar #21 linux 管道流式分析日志都是用这种方式提取,包括一些日志软件
    ragnaroks
        29
    ragnaroks  
       2022-08-30 08:15:49 +08:00
    这个笑话我在学校学 C 的时候老师就讲过了,大意是正则晦涩难懂,其实无他手熟尔
    jackmod
        30
    jackmod  
       2022-08-30 08:42:54 +08:00
    regex 是天书,非常需要注释。所以每写一条都要在旁边写一些例子,便于后期阅读。
    answerhuang
        31
    answerhuang  
       2022-08-30 09:14:36 +08:00
    @HankAviator 自己写出同样功能的代码, 效率不一定比正则好. 所以放心用吧.
    jinliming2
        32
    jinliming2  
       2022-08-30 09:34:22 +08:00 via iPhone
    感觉还是因为害怕使用,所以不愿意用,尽可能避免用。
    但是经常用的话,看正则跟看普通代码一样没啥区别,逻辑不复杂的正则根本不需要注释。除非括号嵌套比较深的,如果正则引擎或语言其他特性支持的话,给换行带个缩进就好。

    我有这样的想法是在之前学 iptables 的时候,一堆参数记不住,都是一个字母的,也没啥具体含义的参数,所以我就不想用。可是 iptables 用的人很多啊,经常用的人这些参数都能直接写出来的,没啥难度哇。
    正则也是,如果自己不会的话,是不愿意用,但自己会用的话,效率还是很高的。
    jinliming2
        33
    jinliming2  
       2022-08-30 09:42:25 +08:00 via iPhone
    @jinliming2 emmmm ,iptables 参数没啥具体意义,这个说法不太对。是说参数含义比较难记。
    bulay
        34
    bulay  
       2022-08-30 09:51:21 +08:00
    @wxf666 具体内容忘了,应该是这个原因.看完之后豁然开朗.其实就是两个贪婪标志加边界问题.被匹配对象太长没有注意到
    AS4694lAS4808
        35
    AS4694lAS4808  
       2022-08-30 10:23:14 +08:00
    以前做过一些硬件报文的解析,几千个字符,每个数据之间用空格隔开,提取数据的时候还是正则香。。。
    11232as
        36
    11232as  
       2022-08-30 16:12:47 +08:00
    regex coach ,很棒的正则验证软件,可惜只有 Windows 端得
    dousha99
        37
    dousha99  
       2022-08-31 10:28:12 +08:00
    感觉标题的这个现象是因为对正则表达式过度神化了。如果你无法用正则语言描述你的数据(或你需要处理的子集),那么你的数据八成是没法通过正则表达式处理的,还是老老实实写字符串处理代码比较好。

    比如「匹配 n 个 a 之后跟着 n 个 b 的字符串」,这个需求是根本不能用正则表达式做的。同理「匹配身份证是否有效」这个需求也是(除了枚举所有有效的身份证号)无法完整地用正则表达式实现的(只是匹配 18 位数字或者 17 位数字带一个 X 是不完整的)。1@1 是合法的邮箱么? 13600000000 是合法的手机号么?很多我们觉得「或许可以用正则处理」的问题实际上是在操作不正则的数据(比如测试邮箱是否合法),或者操作虽然因是有限语言而正则但是枚举所有句子根本不可行的数据(比如测试身份证号是否合法)。

    当然,算上 Perl 给大家带来的那种 irregular 的正则,或许可以处理一点点上下文无关的数据。但还是,很怪。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   959 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 21:12 · PVG 05:12 · LAX 13:12 · JFK 16:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.