首页 > 解决方案 > Python Regex[Forking] - 根据术语捕获组,但如果遇到集合中的另一个术语则跳过

问题描述

首先,我将@checkmate 提出这个问题,因为发布的解决方案不能准确地满足他在“预期输出”中发布的内容。我不确定他是否没有注意或只是发布不正确,但准确地解决这个问题确实可以帮助我的个人项目中的“我”: Get number present after a specific pattern of a matching string in Python

在他的预期输出中,他发布了:

这是预期的输出:

样本输出:

{'Ref.': 'UV1234'}
{'Expedien N°': '18-0022995'}
{'Expedien N°': '18-0022995'}
{'Expedien': '1-21-212-16-26'}
{'Reference' : 'RE9833'}

请注意,"tramite"在他的“预期输出”中明确忽略了这一点。还要注意,他在该行中错误地发布了他的预期输出,"{'Ref.': 'UV1234'}"因为'UV1234'从未出现在字符串中。我想他的意思是"{'Ref.': '1234567'}"。是的,我试过和他们俩聊天,但没有运气。

.

作为回应,我想出了一个超具体的解决方案,它会跳过"tramite",但只要有轻微的差异,正则表达式就会被破坏。此外,因为"Ref.:"存在 with 行,然后是"Expedien N° [Numbers]"对正则表达式 yield 的编辑,"Ref."与 the 一起被捕获"[Numbers]"并被"Expedien N°"忽略,而不是"Expedien N° [Numbers]"(下面是这个有缺陷的变体的示例)。而且我确实更喜欢使用"re.findall",但我很清楚它不会递归地遍历字符串。如果我只能通过 来达到下面的效果"re.search",那么我仍然需要弄清楚如何用它来解决它。.

在Python中匹配字符串的特定模式之后获取数字

>>> import re

>>> string = '''some text before Expedien: 1-21-212-16-26 some random text
Reference RE9833 of all sentences.
abc
123
456
something blah blah Ref.: 
tramite  1234567
Ref.:
some junk Expedien N° 18-00777 # some new content
some text Expedien N°18-0022995 # some garbled content'''

>>> re.findall('(?:(Expedien[\s]+N\S|Ref\.(?!:[\S\s]{,11}Expedien)|Reference|Expedien))[\S\s]*?([A-Z\-]*(?:[\d]+)[\S]*)', string)

[('Expedien', '1-21-212-16-26'), ('Reference', 'RE9833'), ('Ref.', '1234567'), ('Expedien N\xb0', '18-00777'), ('Expedien N\xb0', '18-0022995')]

缺陷:

- 为了正确捕捉,它部分依赖于“Ref.(?!:[\S\s]{,11}Expedien)”

- 首先需要编辑“11”以说明捕获组之间可能存在的其他信息长度,我无法弄清楚,所以现在它不灵活

- 其次,如果在字符串中需要捕获的内容后面是“参考”或我的另一个术语列表,而不是“Expedien”(再次,它太具体),那么第三个“参考”。将被错误捕获

.

.

.

在这个轻微的变体中,我没有指定 11 的范围并消除后视"Ref.""Ref."与数字一起被捕获,"Expedien N°"并且应该被捕获而不是"Ref.", 被忽略

>>> re.findall('(?:(Expedien[\s]+N\S|Ref\.|Reference|Expedien))[\S\s]*?([A-Z\-]*(?:[\d]+)[\S]*)', string)

[('Expedien', '1-21-212-16-26'), ('Reference', 'RE9833'), ('Ref.', '1234567'), ('Ref.', '18-00777'), ('Expedien N\xb0', '18-0022995')]

.

.

.

所以,我想知道:

如果所需的查询发生在我拥有的列表中的一个术语与该列表中存在的另一个术语之间,如何使正则表达式不捕获?

.

.

所需的输出如下,但我想知道如何更可靠地获得它,因为我上面的内容非常具体:

[('Expedien', '1-21-212-16-26'), ('Reference', 'RE9833'), ('Ref.', '1234567'), ('Expedien N\xb0', '18-00777'), ('Expedien N\xb0', '18-0022995')]

标签: pythonregexskip

解决方案


有点长,但这个正则表达式应该对你有用,并且具有负面的前瞻性:

(Ref\.:|Reference|Expediente|Expediente No|Expedien N°|Exp\.No|Expedien)\s*(?:(?!Ref\.:|Reference|Expediente|Expediente No|Expedien N°|Exp\.No|Expedien).)*?([A-Z]*\d+(?:-[A-Z]*\d+)*)

正则表达式演示

(?!...)是负前瞻,以确保我们不匹配重叠的标签。


推荐阅读