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

Python Regex[Forking] - Capture Groups Based on Terms but Skipping if another Term in the set is encountered

首先,我从 @checkmate 那里分叉了这个问题,因为发布的解决方案不能准确满足他在 "Expected Output." 中发布的内容,我不确定他是否没有注意或者只是发错了,但是准确地解决这个问题确实可以帮助 'me' 我的个人项目:

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

This is the expected output:

Sample output:

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

请注意,"tramite" 在他的 "Expected Output." 中被明确忽略 另请注意,他在 "{'Ref.': 'UV1234'}" 行错误地发布了他的预期输出,因为 'UV1234' 永远不会出现在字符串中。我认为他的意思是 "{'Ref.': '1234567'}"。是的,我试过和他们两个聊天,但没有成功。

.

作为回应,我想出了一个超具体的解决方案,它跳过了 "tramite",但只要有轻微的变化,正则表达式就会被破坏。此外,由于带有 "Ref.:" 的行存在并且随后是对正则表达式的 "Expedien N° [Numbers]" 编辑,因此 "Ref." 被捕获,同时 "[Numbers]""Expedien N°" 被忽略,而不是 "Expedien N° [Numbers]"(下面是这个有缺陷的变体的示例)。 我更喜欢使用 "re.findall" 但我很清楚它不会递归地循环遍历字符串。如果下面的内容只能通过 "re.search" 实现,我还需要弄清楚如何解决它。.

>>> 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”以说明捕获组之间可能存在的其他信息长度,我无法弄清楚,所以现在不灵活

- 其次,如果在字符串中需要捕获的内容后跟 "Reference" 或我的另一个术语列表,而不是 "Expedien"(同样,它太具体了)那么第三个 "Ref." 将被错误地捕获

.

.

.

在这个轻微的变体中,我没有指定 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')]

有点长,但这个正则表达式应该对你有用:

(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+)*)

RegEx Demo

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