regex 正则表达式:如何在不同的捕获组时多次匹配字符串

nimxete2  于 2023-03-09  发布在  其他
关注(0)|答案(4)|浏览(218)

我有一个字符串,看起来像这样:
AB
我想用一个如下所示的正则表达式来捕获它:
(?P<GRP1>(A|D))?(?P<GRP2>(A|C))?B
有没有一个python函数可以为字符串生成两个匹配项?第一个是将A作为GRP1的一部分捕获,第二个是将其作为GRP2的一部分捕获?
我尝试了re.fullmatchre.findall这样的函数,但它们都只将A捕获为GRP1的一部分。
我正在寻找的函数在匹配DBCB时会产生一个匹配项,但对于AB会产生两个匹配项,A可能属于的每个组都有一个匹配项。

t1qtbnec

t1qtbnec1#

这不是regex设计的目的。Regex是关于匹配输入的范围与模式。所以输入的任何范围要么匹配要么不匹配。范围在这个过程中被“消耗”,也就是说,同一个范围不能匹配模式两次。另一方面,一个模式可以匹配多个不重叠的范围,这就是findall的目的。
有一些高级正则表达式技术在匹配时不消耗任何字符(lookahead/lookbehind),但这些技术本质上也不捕获任何输入,这使它们对您毫无用处。
通常这是一个应该开始考虑不使用正则表达式或至少不使用 only 正则表达式的点。
我考虑可能的解决办法
1.使用两个正则表达式模式,每个GRP一个。这将使总体结果成为一个元组,表示0-2个匹配项,表示无、GPR 1、GPR 2或GPR 1 + GPR 2
1.使用一个正则表达式模式,但要像(?P<GRP1>(D))?(?P<GRP2>(C))?(?P<GRP1_2>(A))?B这样重新构造它,即为可能发生的每一件事都有一个单独的组。GRP1_2代表GRP1&GRP2的情况。因此,例如,如果你的目标是计算GRP 1和GRP 2匹配,那么你会将GRP1_2计入两者。

relj7zay

relj7zay2#

是的,肯定的:
您可以使用预视:

(?=(?P<GRP1>(A|D)))(?=(?P<GRP2>(A|C)))\wB

这基本上是零宽度Assert-意味着它将捕获需要的组,但在实际匹配中不占用空间。
https://regex101.com/r/o1petz/1

1zmg4dgp

1zmg4dgp3#

我认为您正在寻找组匹配--组是基于“()”创建的

import re

a = re.search('(.*)(.xlsx)', 'doc.xlsx')

print(a.group(1))
print(a.group(2))

此示例将打印

doc
.xlsx
whlutmcx

whlutmcx4#

如果要在AB中捕获2次A,并且只在DBCB中捕获一次DC,则可以在前瞻Assert中使用捕获组,并使捕获组为可选。

(?=(?P<GRP1>[AD])?)(?=(?P<GRP2>[AC])?)[A-Z]B
    • 说明**
  • (?=正向前瞻
  • (?P<GRP1>[AD])?命名组 * GRP1 *,可选匹配AD
  • )关闭前瞻
  • (?=正向前瞻
  • (?P<GRP2>[AC])?命名组 * GRP2 *,可选匹配AC
  • )关闭前瞻
  • [A-Z]B匹配字符A-Z后跟B

请参见regex demoPython demo

pattern = r"(?=(?P<GRP1>[AD])?)(?=(?P<GRP2>[AC])?)[A-Z]B"
s = "AB\nDB\nCB"
matches = re.finditer(pattern, s)

for _, m in enumerate(matches, start=1):
    print([g for g in m.groups() if g])

产出

['A', 'A']
['D']
['C']

如果不想匹配任何跟在B后面的字符,而只想匹配ACD

(?=(?P<GRP1>[AD])?)(?=(?P<GRP2>[AC])?)[ACD]B

Regex demo

相关问题