1

要更改文本周围的标签对,这个 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 语句更健壮吗?

4

1 回答 1

5

通常有两种可能性(PostreSQL 的正则表达式引擎似乎都支持这两种可能性)。

  1. 使重复不贪婪:

    <i>(.+?)</i>
    
  2. 使用负前瞻来确保您使用除以下内容之外的任何内容</i>

    <i>((?:(?!</i>).)+)</i>
    

在这两种情况下,我都删除了不必要的捕获。您\1现在可以在替换字符串中使用。

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

从某种意义上说,您拥有的方法已经很强大,您永远无法超越</i>. 但同时您的方法不允许嵌套标签(因为重复不能超过嵌套对的结束标签)。

但是,您应该注意,正则表达式并不能真正胜任解析/操作 HTML 的工作。如果标签中有多余的空格怎么办?或者如果开始标签有属性怎么办?或者,如果其中一个或两个标签出现在属性名称或注释中怎么办?

于 2012-12-08T15:26:52.767 回答