Postgres Regex贪婪控制

时间:2012-12-08 15:21:36

标签: regex postgresql regex-greedy

要更改文本周围的标记对,此Postgres SELECT表达式适用于我:

select regexp_replace('The corpse of the huge <i>fin whale</i> created a spectacle on <span class="day">Friday</span> as <i>people</i> wandered the beach to observe it.',
                      '(<i>)([^/]+)(</i>)',
                      '<em>\2</em>',
                      'g');

我担心参考二号过度贪婪。我第一次尝试参考第二个是(。+),这是一个失败。 ([^ /] +)效果更好。但我不知道它是否足够好。

可以做些什么来使SELECT语句更健壮吗?

1 个答案:

答案 0 :(得分:5)

通常有两种可能性(and both seem to be supported by PostreSQL's regex engine)。

  1. 不重复的重复:

    <i>(.+?)</i>
    
  2. 使用negative lookahead确保您使用</i>以外的任何内容:

    <i>((?:(?!</i>).)+)</i>
    
  3. 在这两种情况下,我删除了不必要的捕获。您现在可以在替换字符串中使用\1

    这两个应该与他们所做的相同。他们的表现可能会有所不同前者需要回溯,而后者必须在每一个位置尝试前瞻。哪一个更快,必须进行分析,甚至可能依赖于单个输入字符串。请注意,由于第二个模式使用贪婪重复,您可以删除尾随</i>,您仍然会得到相同的结果。

    您所拥有的方法已经非常强大,因为您永远无法超越</i>。但与此同时,您的方法不允许嵌套标记(因为重复不能超过嵌套对的结束标记)。

    但是,您应该注意regular expressions are not really up to the job of parsing/manipulating HTML。如果您的代码中有多余的空格怎么办?或者如果开始标记有属性怎么办?或者如果一个或两个标签出现在属性名称或注释中会怎么样?