1

首先,我知道正则表达式不适合解析 xml,我真的应该使用 xml 解析器。也许我的问题是一个很好的例子,说明为什么这是真的。

话虽如此,我需要做的只是一次性搜索和替换一些 XML 文件。另外,我对正则表达式比较陌生,所以我希望更好地理解正则表达式,以及为什么它对 XML 来说是个坏主意。

我有以下 XML(原始文件在标签之间没有空格!):

<tag1>
    <tag2>Doesn't matter what is here</tag2>
</tag1>
<tag1>
    <tag2>Anything can <b>go<b> here</tag2>
    <tag3>Hi there</tag3>
</tag1>

我需要将 tag3 内的“Hi there”拆分为两个部分,它们都包含在 tag1 中,并且如果存在 tag2 则具有相同的 tag2,即:

<tag1>
    <tag2>Doesn't matter what is here</tag2>
</tag1>
<tag1>
    <tag2>Anything can <b>go<b> here</tag2>
    <tag3>Hi</tag3>
</tag1>
<tag1>
    <tag2>Anything can <b>go<b> here</tag2>
    <tag3>there</tag3>
</tag1>

我最初的想法是为 tag2 使用一个带有非贪婪量词的可选组,如下所示:

<tag1>(<tag2>.*?</tag2>)?<tag3>Hi there</tag3></tag1>

并替换为(Java 语法)

<tag1>$1<tag3>Hi</tag3></tag1><tag1>$1<tag3>there</tag3></tag1>

但是,那 。*?还是太贪心了;它从 tag1 的第一个开始到 tag1 的最后一个结束匹配。执行此操作的正确正则表达式方法是什么?或者这对正则表达式来说是一个难题?这是为什么对 XML 使用正则表达式是个坏主意的原因之一吗?

我发现使用原子组完全符合我的要求:

<tag1>(?>(<tag2>.*?</tag2>))?<tag3>Hi there</tag3></tag1>

但是我真的不明白为什么会这样。为什么这行得通,这是否足够可靠?

4

1 回答 1

1

好的,我尝试向您解释正则表达式的行为:

1.第一个Regex的匹配行为

<tag1>(<tag2>.*?</tag2>)?<tag3>Hi there</tag3></tag1>

模式开始匹配<tag1>then there is a <tag2>this 也匹配,然后它与.*?until the first匹配</tag2>。很好,但是模式需要<tag3>遵循,没有,所以正则表达式会回溯并将第一个</tag2>与匹配.*?,然后.*?匹配任何东西直到下一个</tag2>。在那里它找到了一个后续<tag3>并且可以成功完成。

2. 原子组版本的匹配行为

<tag1>(?>(<tag2>.*?</tag2>))?<tag3>Hi there</tag3></tag1>

模式开始匹配<tag1>then there is a <tag2>this 也匹配,然后它与.*?until the first匹配</tag2>

到目前为止,行为与第一个正则表达式完全相同。

但是现在没有<tag3>跟随,但是原子组阻止了回溯,所以正则表达式失败了。

它在第二个<tag1>成功的地方重新开始。

于 2012-10-23T10:07:57.870 回答