在一些场景下,我们不需要回溯,匹配不上返回失败就好了,因此正则中还有另外一种模式,独占模
    式,它类似贪婪匹配会尽可能多地去匹配,但匹配失败就结束,不会进行回溯,因此在一些场合下性能
    会更好,具体的方法就是在数量词后面加上加号 + 。
    独占模式下:

    1. regex = "xy{1,3}+yz"
    2. text = "xyyz"

    y{1,2}+尽可能多的匹配前两个y,不回溯导致正则z前面的y匹配不上:
    image.png
    python的标准库re并不支持独占模式,会报错:

    1. >>>importre
    2. >>>re.findall('xy{1,3}+z','xyyz')
    3. Traceback(mostrecentcalllast):
    4. File"<stdin>",line1,in<module>
    5. File"D:\Anaconda3\lib\re.py",line223,infindall
    6. return_compile(pattern,flags).findall(string)
    7. File"D:\Anaconda3\lib\re.py",line286,in_compile
    8. p=sre_compile.compile(pattern,flags)
    9. File"D:\Anaconda3\lib\sre_compile.py",line764,incompile
    10. p=sre_parse.parse(p,flags)
    11. File"D:\Anaconda3\lib\sre_parse.py",line930,inparse
    12. p=_parse_sub(source,pattern,flags&SRE_FLAG_VERBOSE,0) File"D:\Anaconda3\lib\sre_parse.py",line426,in_parse_sub notnestedandnotitems))
    13. File"D:\Anaconda3\lib\sre_parse.py",line654,in_parse
    14. source.tell()-here+len(this))
    15. re.error:multiplerepeatatposition7

    python上要使用独占模式需要安装regex 模块:

    1. pip install regex

    再次测试:

    1. >>>importregex
    2. >>>regex.findall(r'xy{1,3}z','xyyz') #贪婪模式
    3. ['xyyz']
    4. >>>regex.findall(r'xy{1,3}+z','xyyz')#独占模式
    5. ['xyyz']
    6. >>>regex.findall(r'xy{1,2}+yz','xyyz')#独占模式[]

    独占模式的典型应用:
    独占模式性能比较好,可以节约匹配的时间和 CPU 资源,但并不是所有的场景都适用,否则也不会出
    现python标准库不支持的场景。下面我们看一个适合适用独占模式的场景。
    阿里技术微信公众号上的发文。Lazada 卖家中心店铺名检验规则比较复杂,名称中可以出现下面这些
    组合:

    • 英文字母大小写;
    • 数字;
    • 越南文;
    • 一些特殊字符,如“&”,“-”,“_”等。

    负责开发的小伙伴在开发过程中使用了正则来实现店铺名称校验:

    1. ^([A-Za-z0-9._()&'\-]|
    2. [aAàÀảẢãÃáÁạẠăĂằẰẳẲẵẴắẮặẶâÂầẦẩẨẫẪấẤậẬbBcCdDđĐeEèÈẻẺẽẼéÉẹẸêÊềỀểỂễỄếẾệỆfFgGhHiIìÌỉ ỈĩĨíÍịỊjJkKlLmMnNoOòÒỏỎõÕóÓọỌôÔồỒổỔỗỖốỐộỘơƠờỜởỞỡỠớỚợỢpPqQrRsStTuUùÙủỦũŨúÚụỤưƯừỪử ỬữỮứỨựỰvVwWxXyYỳỲỷỶỹỸýÝỵỴzZ])+$

    这个正则比较长但很好理解,简化一下主体结构,即:

    1. ^([符合要求的组成1]|[符合要求的组成2])+$

    正则中有的加号 + 表示前面的内容出现一到多次进行贪婪匹配,这样会导致大量回溯,占用大量 CPU
    资源,引发线上问题。
    我们只需要将贪婪模式改成独占模式(加号 + 后面再加个加号 + )就可以解决这个问题,即:

    1. ^([符合要求的组成1]|[符合要求的组成2])++$

    这个例子中,匹配不上时证明店铺名不合法,不需要进行回溯,因此我们可以使用独占模式,但要并不
    是所有的场合都可以用独占模式解决,首先要保证正则能满足功能需求。
    仔细再看一下 这个正则发现 “组成 1” 和 “组成 2” 部分中,A-Za-z 英文字母在两个集合里面重复出现
    了,这会导致回溯后的重复判断,去掉重复字符也能大幅度减少正则的计算量。
    这个问题将在文末的补充资料中继续详解。