作为介绍性说明,我知道有关解决正则表达式问题的古老说法,我也了解使用RegEx处理XML的注意事项。但是请跟我说一下......
我正在尝试进行RegEx搜索并替换一组字符。我事先并不知道这个小组的匹配频率,但我想只搜索某个特定的上下文。
一个例子:
如果我有以下字符串"**ab**df**ab**sdf**ab**fdsa**ab**bb"
并且我想搜索"ab"
并替换为"@ab@"
,则使用以下正则表达式可以正常工作:
搜索正则表达式:
(.*?)(ab)(.*?)
替换:
$1@$2@$3
我总共得到了四场比赛,正如预期的那样。在每个匹配中,组ID是相同的,因此后引用($ 1,$ 2 ...)也可以正常工作。
但是,如果我现在向字符串添加某个上下文,则上面的正则表达式失败:
搜索字符串:
<context>abdfabsdfabfdsaabbb</context>
搜索正则表达式:
<context>(.*?)(ab)(.*?)</context>
这只会找到第一场比赛。
但即使我在原始正则表达式中添加了非捕获组,它也不起作用("<context>(?:(.*?)(ab)(.*?))*</context>"
)。
我想要的是第一次搜索中的匹配列表(没有上下文),在每次匹配中,组ID是相同的。
知道如何实现这一目标吗?
答案 0 :(得分:1)
您的要求类似于this question中的要求:匹配并捕获前缀和后缀之间的模式的多个实例。使用this answer of mine中描述的方法:
(?s)(?:<context>|(?!^)\G)(?:(?!</context>|ab).)*ab
根据需要添加捕获组。
请注意,正则表达式仅适用于仅允许仅包含文本的标记。如果标记包含其他标记,则它将无法正常工作。
它还匹配ab
标记内的<context>
而没有结束标记</context>
。如果你想阻止它,那么:
(?s)(?:<context>(?=.*?</context>)|(?!^)\G)(?:(?!</context>|ab).)*ab
让我们打破正则表达式:
(?s) # Make . matches any character, without exception
(?:
<context>
|
(?!^)\G
)
(?:(?!</context>|ab).)*
ab
(?:<context>|(?!^)\G)
确保我们要么进入新的<context>
标记,要么继续上一个匹配并尝试匹配更多的子模式实例。
(?:(?!</context>|ab).)*
匹配我们不关心的任何文字(不是ab
)并阻止我们越过结束标记</context>
。然后我们在最后匹配我们想要ab
的模式。