正则表达式通过分隔符捕获可选组

Regex capture optional groups by delimiters

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

"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 时才执行此操作。试图让后面的组成为可选的让我把事情搞砸了:

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

如何正确捕获它们?

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

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

看到regex demo,模式匹配

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

在这种情况下,我会使用 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 dash never出现在您的示例数据中。