假设我有以下文本:
Name: John DoetAddress: Street 123 ABCtCity: MyCity
我有一个正则表达式(有点复杂,但归根结底是这样(:
^(?:(?:(?:Name: (.+?))|(?:Address: (.+?))|(?:City: (.+?)))t*)+$
它有三个捕获组,可以捕获Name、Address和City的值(如果它们出现在文本中(。以下是更多示例:https://regex101.com/r/37nemH/6.EDIT排序不是预先固定的,也可能出现字段由t
字符分隔的而不是的情况。
现在这一切都很好,我唯一的小问题是当一个字段在同一文本中出现两次时,正如我在regex101:上的最后一个例子所示
Name: John DoetAddress: Street 123 ABCtCity: MyCitytAddress: Other Address
我希望第二个捕获组匹配第一个地址,即Street 123 ABC
,并且最好让第二个事件在"城市"组内匹配,即
1: John Doe
2: Street 123 ABC
3: MyCitytAddress: Other Address
从概念上讲,我试着用一个否定的后备来做这件事,例如用(?:(?<!.*Address: )Address: (.+?))
替换(?:Address: (.+?))
,即确保另一个Address:
标签不会在文本中的某个地方进行Address:
匹配。但是,负向后看不允许任意长度,所以这显然是行不通的。
这可以使用regex实现吗?如何实现?
对于您提出的问题,您可以将此正则表达式与条件构造一起使用:
^.*?(?:(?:Name: (.+?)|(Address: )(.+?)|City: ((?(2).*?Address: )*.+?))t*)+$
RegEx演示
您的值在捕获的组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`
如果单词顺序可以是任意的,并且部分或全部项目可能会丢失,那么使用3个单独的模式来提取所需的位会容易得多。
名称(演示(:
^.*?Name:s*(.*?)(?=s*(?:Name:|Address:|City:|$))
城市(演示(:
^.*?City:s*(.*?)(?=s*(?:Name:|Address:|City:|$))
地址(演示(:
^.*?Address:s*(.*?)(?=s*(?:Name:|Address:|City:|$))
详细信息
^
-字符串的开头.*?
-换行字符以外的任何0+个字符,尽可能少Address:
-一个用于查找预期匹配项的关键字s*
-0+空白(.*?)
-第1组:除换行字符外的任何0+个字符,尽可能少(?=s*(?:Name:|Address:|City:|$))
-最多但不包括0个或多个空格,后面跟有Name:
、Address:
、City:
或字符串末尾