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

一种傻瓜式生成 regex pattern 的设想

  •  
  •   kongque2016 · 2018-05-04 19:50:33 +08:00 · 1491 次点击
    这是一个创建于 2155 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我有一个想法,能不能用常规编程语言来构建正则表达式,基本的实现方案是:
    1, 提供一个 Class,类的名字叫 Regex
    2, 提供一组基本的 API:
    Regex Any(string); //字符群中的任意一个
    Regex None(string); //字符群外的任意一个
    Regex Between(string); //字符区间的任意一个
    Regex NotBetween(string); //字符区外的任意一个
    Regex Regex(string); //把 string 转换成 Regex 对象
    Regex Mustnot(Regex); //negative look ahead
    ...
    这些 API 接受字符串参数,返回一个 Regex 对象.
    此外,Regex 对象本身也有 method,像:
    Regex Regex::repeat(min, max); //重复 min 至 max 次

    3, Regex 对象之间是可以运算的(通过重载操作符), 运算的结果还是 Regex 对象.
    减号是取补集,像:
    Between("az") - Any("sdf") 是从 a-z 范围内挖掉 s,d,f 这三个字符.
    竖线|是取并集,加号+是连接, 感叹号!是取反,表示该集合之外的所有字符.

    4, 通过 Regex 对象,帮用户(一个程序员)生成它想要的 pattern 字符串.

    下面举几个例子,先来几个简单点儿的:
    匹配数字: Regex digit = Between("09")
    匹配字母: Regex alpha = Between("az", "AZ") //可以接受多个 range 参数
    匹配空白: Regex space = Any("\n\t\f\r\s")

    再来个稍微复杂些的,匹配 c 的变量名:
    Regex cword =
    Mustnot( Between("09")) //不能以数字开头
    + ( Between("09", "az", "AZ") | "_" ).repeat(1, 255); //变量名长度小于 256

    其实能写的更简单点儿,因为之前已经定义过 digit, alpha 这些,可以当模板用:
    Regex cword =
    Mustnot( digit )
    + (digit | alpha | "_").repeat(1, 255)

    前面说过 Regex 对象之间可以运算,所以上面有 digit | alpha | "_" 这样的写法. 只不过第三个运算对象"_"是 string 类型,我是嫌写成 Regex("_")麻烦,string 跟 Regex 对象运算时会自动的隐式转换为 Regex 对象.这是设计细节,就不多说了.


    我觉得这种傻瓜式的构建 regex 的好处是,能把初学者从正则表达式的晦涩的文法里解放出来,有精力去体会 Regex 这项发明背后的基本思想. 即使这样写的稍慢一些,但总归能写出来,不至于要去网上求别人.


    我现在正在着手写这个库,但总怀疑已经有人设计出来了,如果你知道的话,请一定赶紧告诉我!
    最后,如果你有什么想法或建议,请不吝赐教.
    CodeingBoy
        1
    CodeingBoy  
       2018-05-04 20:51:13 +08:00
    其实就是类似于各数据库框架中用于构建 Query 的 Builder 一样,写一个 Regex 的 Builder 出来。
    以 "Regex Builder" 为关键词可以查到以下可能相似的内容:
    https://www.regexbuddy.com/create.html
    http://buildregex.com/
    https://github.com/bruntonspall/regex-builder

    日常使用这些 Query Builder 的时候可能会在构造 Query 的过程中动态添加条件,所以还是有必要的;但是正则表达式一旦构造出来了后,就很少再去改动它。也就是说构造正则的过程可以和代码独立开来,不需要整合到语言或者做成 Class,只需要做成类似上面的网站或者工具就可以了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1228 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 23:22 · PVG 07:22 · LAX 16:22 · JFK 19:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.