假设我有以下文字:
Fragment
我有一个正则表达式(稍微复杂一点,但归结为这一点):
Objects
具有三个捕获组,它们可以捕获名称,地址和城市的值(如果它们出现在文本中)。这里有更多示例:https://regex101.com/r/37nemH/6。 编辑顺序不是预先固定的,也可能发生字段不用Name: John Doe\tAddress: Street 123 ABC\tCity: MyCity
字符分隔的情况。
现在这一切都很好,我唯一的轻微问题是当一个字段在同一文本中出现两次时,如我在regex101上的最后一个示例中所见:
^(?:(?:(?:Name: (.+?))|(?:Address: (.+?))|(?:City: (.+?)))\t*)+$
我想要的是让第二个捕获组匹配 first 地址,即\t
,最好让第二个匹配项在“ City”组中匹配,即
Name: John Doe\tAddress: Street 123 ABC\tCity: MyCity\tAddress: Other Address
从概念上讲,我尝试使用反面的方式进行此操作,例如将Street 123 ABC
替换为1: John Doe
2: Street 123 ABC
3: MyCity\tAddress: Other Address
,即确保另一个(?:Address: (.+?))
标签未在文本中进行(?:(?<!.*Address: )Address: (.+?))
匹配。但是,负向后看不允许任意长度,因此这显然行不通。
可以使用正则表达式来实现吗?
答案 0 :(得分:3)
对于您陈述的问题,可以将此正则表达式与条件构造一起使用:
^.*?(?:(?:Name: (.+?)|(Address: )(.+?)|City: ((?(2).*?Address: )*.+?))\t*)+$
您的值在已捕获的组1、3、4中可用。
捕获组2用于文字标签"Address: "
。
在这里,(?(2).*?Address: )*
是一个条件构造,这意味着如果存在捕获的第2组,则在第4组匹配文本中,直到找到下一个Address:
(此匹配项为0或更多)。
对于文本Name: John Doe Address: Street 123 ABC City: MyCity Address: Second address
,它将具有以下匹配项:
Group 1. 169-177 `John Doe`
Group 2. 178-187 `Address: `
Group 3. 187-201 `Street 123 ABC`
Group 4. 210-240 `MyCity Address: Second address`
答案 1 :(得分:2)
如果单词顺序可以是任意的并且某些或所有项目可能会丢失,则使用3个独立的模式来提取所需的位会容易得多。
名称(demo):
^.*?Name:\s*(.*?)(?=\s*(?:Name:|Address:|City:|$))
城市(demo):
^.*?City:\s*(.*?)(?=\s*(?:Name:|Address:|City:|$))
地址(demo):
^.*?Address:\s*(.*?)(?=\s*(?:Name:|Address:|City:|$))
详细信息
^
-字符串的开头.*?
-除换行符以外的任何0+个字符,并且尽可能少Address:
-停在该关键字并寻找预期匹配项的关键字\s*
-超过0个空格(.*?)
-第1组:除换行符以外的任何0+个字符,并且尽可能少... (?=\s*(?:Name:|Address:|City:|$))
-最多但不包括0个或多个空格,后跟Name:
,Address:
,City:
或字符串结尾。