代码之家  ›  专栏  ›  技术社区  ›  Colonel Beauvel

多分离器分离保留分离器

  •  0
  • Colonel Beauvel  · 技术社区  · 8 年前

    我有以下字符串输入:

    "11A4B"
    "5S6B"
    

    ["11A", "4B"]
    ["5S", "6B"]
    

    我可以忍受 split 从 re (将括号放在分隔符模式上还返回使用的分隔符):

    re.split("([ABS])", "11A4B")
    #['11', 'A', '4', 'B', '']
    

    可以玩到想要的解决方案,但我想知道是否有一个纯正则表达式解决方案?

    4 回复  |  直到 8 年前
        1
  •  3
  •   Wiktor Stribiżew    8 年前

    在所有Python版本中都可以使用的解决方案是基于PyPi的 regex regex.split 和 regex.V1 标志:

    import regex
    ss = ["11A4B","5S6B"]
    delimiters = "ABS"
    for s in ss:
        print(regex.split(r'(?<=[{}])(?!$)'.format(regex.escape(delimiters)), s, flags=regex.V1))
    

    Output

    ['11A', '4B']
    ['5S', '6B']
    

    细节

    • (?<=[ABS]) -与紧跟在后面 A , B S
    • (?!$) -这不会紧跟在字符串末尾(因此,字符串末尾的所有位置都将失败)。

    这个 regex.escape 仅在分隔符列表中可能有特殊的regex字符时使用,如 ^ , \ , - ] .

    在 Python 3.7, re.split 也可以使用零长度匹配进行拆分,因此,以下操作也将起作用:

    re.split(r'(?<=[{}])(?!$)'.format(re.escape(delimiters)), s)
    

    否则,你可以使用变通方法,比如

    re.findall(r'[^ABS]*[ABS]?', s) # May result in empty items, too
    re.findall(r'(?s)(?=.)[^ABS]*[ABS]?', s) # no empty items due to the lookahead requiring at least 1 char
    

    见 regex demo .

    细节

    • (?s) - .
    • (?=.) -一个字符应立即出现在当前位置的右侧
    • [^ABS]* -除 一个 乙 和
    • [ABS]? -1或0(=可选) 一个 , 乙 或 S公司
        2
  •  3
  •   CertainPerformance    8 年前

    使用 re.findall 相反,并匹配后跟 A , B ,或 S

    re.findall(r'\d+[ABS]', '11A4B')
    

    输出:

    ['11A', '4B']
    

    re.findall(r'[^ABS]+[ABS]', 'ZZZAYYYSXXXB')
    

    输出:

    ['ZZZA', 'YYYS', 'XXXB']
    
        3
  •  2
  •   Jan    8 年前

    您可以使用lookarounds:

    (?<=[ABS])(?!$)
    

    硒 a demo on regex101.com

        4
  •  1
  •   Daniel    8 年前

    使用 findall :

    re.findall('(.*?(?:[ABS]|.$))', "11A4B5")