2013-10-06 39 views
0

假设我有一个标签<tag>,我想在我的字符串中匹配<tag>...<tag>组。我可以沿着<tag>.*<tag>的方向使用正则表达式。这匹配<tag>foo<tag>,这很好,但它也匹配<tag>foo<tag>bar<tag>,这是我不想要的行为。我想要<tag>foo<tag>匹配,然后bar被排除,然后标记结束成为下一个匹配的开始。我该怎么做呢?红宝石正则表达式 - 防止重叠匹配

+0

你有任何HTML字符串? –

+0

这不一定是HTML - “”可以代替任何序列。 – Kvass

+0

任何重复序列都会很快显示出使用正则表达式的缺点,而且您调整避免碰撞/重叠的模式的工作将会天壤之寒。 *如果你正在使用HTML或XML,不要打扰正则表达式,如果你的需求超出了微不足道的用途。相反,使用像Nokogiri这样的解析器。你的大脑稍后会感谢你。 –

回答

4

最简单的解决方法是使用一个懒惰的quantifier其中?迫使.*几个字符地匹配(而不是,尽可能缦.*将尝试匹配):

<tag>.*?<tag> 

一个更安全,更明确的解决方案是使用一个negative lookahead assertion

<tag>(?:(?!<tag>).)*<tag> 

虽然在目前的情况下,在行为上没有差异,第二个是扩展处理打开/关闭标签,确保嵌套的标签不匹配错误:

<tag>(?:(?!</?tag>).)*</tag> 

当应用于<tag>foo<tag>bar</tag>baz</tag>会匹配<tag>bar</tag>,而不是<tag>foo<tag>bar</tag>作为一个懒惰量词的解决方案。

+2

你能解释一下是什么让它“更安全”吗? – Kvass

2

您使用懒惰版本.*存在的:

<tag>.*?<tag> 
    ^

?使得.*比赛最多直到<tag>的第一场比赛。

+0

我不确定我是否遵守 - 不会'''只是冗余,因为'。*'意味着零个或多个任何字符? – Kvass

+0

@Kvass在这里,'?'作为'修饰符'而不是'0或1次'。 '。*?'被认为是'懒',而'。*'被认为是'贪婪'。 – Jerry