【问题标题】:Regex capture optional groups by delimiters正则表达式通过分隔符捕获可选组
【发布时间】:2021-06-15 08:28:44
【问题描述】:

我需要通过引用文本和 @ 作者和 # 类别分隔符来解析字符串引用。作者和类别按顺序排列,但是是可选的。像这样:

"When in doubt - don’t. @Ben Franklin #decisions"

{'text': 'When in doubt - don’t.', 'author': 'Ben Franklin', 'category': 'decisions'}

"When in doubt - don’t. #decisions"

{'text': 'When in doubt - don’t.', 'category': 'decisions'}

"When in doubt - don’t. @Ben Franklin"

{'text': 'When in doubt - don’t.', 'author': 'Ben Franklin'}

如果分隔符和空格粘在捕获的组上也没关系,我可以稍后将它们剥离。我当前的正则表达式:

^(.*?)(@.*)(#.*)$

仅当@author 和#category 都出现在输入字符串中时才起作用。试图让后面的组成为可选的让我搞砸了:

^(.*?)(@.*)?(#.*)?$

如何正确捕捉它们?

【问题讨论】:

标签: python regex python-re


【解决方案1】:

假设@#只出现在作者或类别前面的字符串末尾,可以使用

^([^@#]*)(@[^#]*)?(#.*)?$

查看regex demo,模式匹配

  • ^ - 字符串开头
  • ([^@#]*) - 第 1 组:除 #@ 之外的任何零个或多个字符
  • (@[^#]*)? - 第 2 组(可选):@,然后是除 # 之外的零个或多个字符
  • (#.*)? - 第 3 组(可选):#,然后是除 # 之外的零个或多个字符
  • $ - 字符串结束。

【讨论】:

    【解决方案2】:

    在这种情况下我会使用 named 组,如下所示

    import re
    text1 = "When in doubt - don’t. @Ben Franklin #decisions"
    text2 = "When in doubt - don’t. #decisions"
    text3 = "When in doubt - don’t. @Ben Franklin"
    pattern = "^(?P<text>.*?)(?P<author>@.*?)?(?P<category>#.*)?$"
    m1 = re.match(pattern, text1)
    m2 = re.match(pattern, text2)
    m3 = re.match(pattern, text3)
    for m in [m1,m2,m3]:
        print(m.group('text'), m.group('author'), m.group('category'), sep='---')
    

    输出

    When in doubt - dont. ---@Ben Franklin ---#decisions
    When in doubt - dont. ---None---#decisions
    When in doubt - dont. ---@Ben Franklin---None
    

    请注意,None 表示 python 的 None 不是文字字符串 "None",我使用 --- 来分隔组,因为 3 x 破折号永远不会出现在您的示例数据中。

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 2020-04-06
      • 2022-06-11
      • 2014-01-28
      相关资源
      最近更新 更多