1

作为介绍性说明,我知道关于使用 regex 解决问题的老话,并且我也知道使用 RegEx 处理 XML 的注意事项。但请容忍我一会儿……

我正在尝试对一组字符进行正则表达式搜索和替换。我事先不知道该组匹配的频率,但我只想使用特定的上下文进行搜索。

一个例子:如果我有以下字符串"**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 都是相同的。

知道如何实现吗?

4

1 回答 1

1

解决方案

您的要求类似于此问题中的要求:匹配并捕获前缀和后缀之间模式的多个实例。使用我的这个答案中描述的方法:

(?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

于 2014-01-29T14:39:56.647 回答