【问题标题】:Python regex multiple matches occurrences between two stringsPython正则表达式在两个字符串之间多次匹配
【发布时间】:2021-07-02 14:18:41
【问题描述】:

我的开始/结束魔术字符串(“X”和“Y”)有一个多行字符串。我正在尝试捕获所有事件,但遇到了一些问题。

这里是代码

testString = '''AAAAAXBBBBBYCCCCCXDDDDDYEEEEEEXFFF
FFFYGGG
'''

pattern = re.compile(r'(.*)X(.*)Y(.*)', re.MULTILINE)

match = re.search(pattern, testString)
print match.group(1) # output: AAAAAXBBBBBYCCCCC
print match.group(2) # output: DDDDD
print match.group(3) # output: EEEEEEXFFF

基本上,我正在尝试捕获以下所有出现的情况(并且我必须保持文本顺序):

  • 魔术起始字符串之前的文本(例如:AAAAA、CCCCC、EEEEEE)
  • 开始/结束魔术字符串之间的文本(例如:BBBBB、DDDDD、FFF\nFFF)
  • 魔术起始字符串后的文本(例如:CCCCC、GGG)

所以我正在尝试打印以下输出:(下面括号中的内容只是注释)

AAAAA (before magic string)
BBBBB (between magic strings)
CCCCC (before/after magic strings, it does not matter. Just the order matters.)
DDDDD (after magic string)

等等。按该顺序打印它们将解决问题。 (然后我可以将每个函数传递给其他函数,...等)

当文本像“AAXBBYCC”这样简单时,代码可以很好地工作,但是对于复杂的字符串,我会失去控制。

有什么想法或替代方法吗?

【问题讨论】:

  • 那些“复杂的字符串”到底是什么,您的确切预期输出是什么?例如,可能存在歧义和/或交错出现,如X1X2Y3X4Y
  • 我使用代码中的 testString 示例编辑了原始帖子。我想在之前或之后获取所有出现的文本,没关系。我想在他们每个人之间获取文本。它基本上用于解析器中以进行进一步的文本处理。 (所以我必须保持处理文本的顺序)。
  • 你写的在魔法开始之后,你的意思是在魔法结束之后吗?你为什么不在那里包含 EEEEEE
  • @j0kzy 是什么让你接受这个特定的答案,因为它似乎没有给出你在问题中所说的想要的输出?

标签: python-3.x regex


【解决方案1】:

你不能直接使用:

pattern = re.compile(r'[^XY]+')
match = re.findall(pattern, testString)
print(match)
# ['AAAAA', 'BBBBB', 'CCCCC', 'DDDDD', 'EEEEEE', 'FFF\nFFF', 'GGG\n']

【讨论】:

  • 这也适用于我提供的示例。问题是我想知道它何时匹配中间的文本。我仍然想念如何做这部分。
【解决方案2】:

您可以匹配第 1 组中除 X 或 Y 之外的任何字符,然后匹配 X 并对 Y 执行相同操作。“魔术字符串之后”部分可以在第三组的前瞻中捕获。

使用[^negated character class 也将匹配换行符以匹配FFFFFF 部分。

([^XY]+)X([^XY]+)Y(?=([^XY]+))
  • ([^XY]+)X 捕获组 1,匹配除 X 或 Y 之外的任何字符 1+ 次,然后匹配 X
  • ([^XY]+)Y捕获组2,匹配除X或Y以外的任何字符1+次,然后匹配Y
  • (?= 正向前瞻,断言直接在右边的是
    • ([^XY]+) 捕获第 3 组,匹配除 X 或 Y 之外的任何字符 1 次以上
  • )关闭前瞻

Regex demo | Python demo

import re

regex = r"([^XY]+)X([^XY]+)Y(?=([^XY]*))"

s = ("AAAAAXBBBBBYCCCCCXDDDDDYEEEEEEXFFF\n"
            "FFFYGGG")

matches = re.findall(regex, s)
print(matches)

输出

[('AAAAA', 'BBBBB', 'CCCCC'), ('CCCCC', 'DDDDD', 'EEEEEE'), ('EEEEEE', 'FFF\nFFF', 'GGG')]

【讨论】:

    【解决方案3】:

    所以我正在尝试打印以下输出:(下面括号中的内容只是注释)

    AAAAA (before magic string)
    BBBBB (between magic strings)
    CCCCC (before/after magic strings, it does not matter. Just the order matters.)
    DDDDD (after magic string)
    

    等等。

    既然开始或结束之前或之后都没有关系,那么简单如下:

    import re
    o = re.split("X|Y", testString)
    print(*o, sep='\n')
    

    【讨论】:

    • 我在打印和“sep”中遇到带有星号的语法错误。使用 Python 3.8.7。
    • 由于您不坚持输出与您的问题中显示的完全相同,您也可以只使用print(o)
    • 是的,这也适用于我提供的示例。但问题是我想知道它何时与中间的文本匹配。我仍然想念如何做这部分。
    • 所以有一个问题你没有在你的问题中提到,你想自己解决?
    • 是的,我发现我的问题不是 100% 清楚。无论如何,我弄清楚了我的问题所在。我必须在星号后添加? 以防止正则表达式变得贪婪。并使用finditer 按顺序返回匹配项。
    猜你喜欢
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多