正则表达式通过分隔符捕获可选组
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出现在您的示例数据中。
我需要通过引用文本和 @ 作者和 # 类别分隔符来解析字符串引用。作者和类别按顺序排列,但可选。像这样:
"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出现在您的示例数据中。