regex 将相同的匹配捕获到不同的组中

ghhaqwfi  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(100)

我有一个很大的关键字列表和它们所属的组。一些相同的关键字属于不同的组。我需要找到所有命名的组。

msg = 'ef'
tmp = re.compile(r'(?P<ABC>ab|ef)|(?P<EFG>cd|ef)')
res = [g.groupdict() for g in tmp.finditer(msg)]

字符串
第一个月
同时,我可以找到以下情况中的所有组:

msg = 'cd ab cd'
[{'ABC': None, 'EFG': 'cd'}, {'ABC': 'ab', 'EFG': None}, {'ABC': None, 'EFG': 'cd'}]

的数据
但我没有找到所有的组。如果文本中有“ef”,我如何找到所有的组(“ABC”,“EFG”)?

camsedfj

camsedfj1#

您可以使用lookarounds将相同的文本捕获到不同的组中:

(?=(?P<ABC>ab|ef)?)   # Lookahead and capture 'ab' or 'ef' into group ABC
                      # if either of them is there
(?=(?P<EFG>cd|ef)?)   # then do the same with 'cd', 'ef' and group EFG,
(?:ab|cd|ef)          # before matching the real thing: a union set of all keywords.

字符串
尝试on regex101.com(请参阅 * 匹配信息 * 面板)。
考虑到这一点,编写一个脚本来生成这样的正则表达式应该是很简单的:

from itertools import chain
import re

keywords_by_group = {
  'ABC': ('ab', 'ef'),
  'EFG': ('cd', 'ef'),
  'HIJ': ('ef', 'hi', 'jk')
}

lookaheads = (
  f'''(?=(?P<{group}>{'|'.join(keywords)})?)'''
  for group, keywords in keywords_by_group.items()
)

regex = re.compile(
  fr'''
  {''.join(lookaheads)}
  (?:{'|'.join(set(chain(*keywords_by_group.values())))})
  ''',
  re.X
)

print(regex.pattern)

'''
(?=(?P<ABC>ab|ef)?)(?=(?P<EFG>cd|ef)?)(?=(?P<HIJ>ef|hi|jk)?)
(?:ab|cd|ef|hi|jk)
'''


试试看:

message = 'cd ab cd ef'
print([match.groupdict() for match in regex.finditer(message)])

'''
[
  {'ABC': None, 'EFG': 'cd', 'HIJ': None},
  {'ABC': 'ab', 'EFG': None, 'HIJ': None},
  {'ABC': None, 'EFG': 'cd', 'HIJ': None},
  {'ABC': 'ef', 'EFG': 'ef', 'HIJ': 'ef'}
]
'''

2w2cym1i

2w2cym1i2#

一旦字符串的一部分被模式的一部分消耗,它将不会被重新考虑用于模式的不同部分。如果你需要找到所有的group-patterns,我们必须在外部使用iterate这个group-patterns:

import re

msg = 'ef'
patterns = {
    'ABC': r'ab|ef',
    'EFG': r'cd|ef'
}

res = {}
for group, pattern in patterns.items():
    if re.fullmatch(pattern, msg):
        res[group] = msg

print(res)  # {'ABC': 'ef', 'EFG': 'ef'}

字符串

相关问题