【发布时间】:2019-04-25 00:48:53
【问题描述】:
假设我有以下文本:
Name: John Doe\tAddress: Street 123 ABC\tCity: MyCity
我有一个正则表达式(有点复杂,但归结为这个):
^(?:(?:(?:Name: (.+?))|(?:Address: (.+?))|(?:City: (.+?)))\t*)+$
它具有三个捕获组,可以捕获名称、地址和城市的值(如果它们出现在文本中)。更多示例如下:https://regex101.com/r/37nemH/6。 EDIT 事先没有固定顺序,也可能出现字段not以\t 字符分隔的情况。
现在这一切都很好,我唯一的小问题是当一个字段在同一文本中出现两次时,如我在 regex101 上放置的最后一个示例所示:
Name: John Doe\tAddress: Street 123 ABC\tCity: MyCity\tAddress: Other Address
我想要的是让第二个捕获组匹配第一个地址,即Street 123 ABC,最好让第二个匹配项在“City”组内匹配,即 p>
1: John Doe
2: Street 123 ABC
3: MyCity\tAddress: Other Address
从概念上讲,我尝试用消极的后视来做到这一点,例如将(?:Address: (.+?)) 替换为(?:(?<!.*Address: )Address: (.+?)),即确保Address: 匹配没有被另一个Address: 标记在文本中的某处进行。但是,消极的后视不允许任意长度,所以这显然是行不通的。
这可以使用正则表达式实现吗?如何实现?
【问题讨论】:
-
尝试连续匹配和捕获值,
^(.*?)Name:\s+(.*?)\s+Address:\s+(.*?)\s+(?:City:\s+(.*?)\s*)?$,参见demo。 -
如果词序可以是任意的,并且可以缺少部分或全部项目,那么使用 3 个单独的模式来提取您需要的位会容易得多。
-
当字段没有明确分隔时,这是否也有效?例如。文字是否符合
Name: John DoeAddress: Street 123 ABC? -
这就像一个魅力。然后我会想像我在问题中提到的那样,将 City 匹配为
MyCity\tAddress: Other Address只是要求太多,不是吗;)
标签: regex capturing-group negative-lookbehind