【问题标题】:Replacing specific substrings between tags替换标签之间的特定子字符串
【发布时间】:2015-04-29 12:23:31
【问题描述】:

我有以下 HTML 文档片段:

<ol>
    <li>some text</li>
    <li>some <strong>more</strong> text</li>
    <li>some more text</li>
</ol>
<ul>
    <li>even more text</li>
    <li>...</li>
</ul>

我想要实现的是用##li##&lt;/li&gt; 替换出现在&lt;ol&gt;&lt;/ol&gt; 之间的所有&lt;li&gt; 实例##/li##&lt;li&gt;&lt;/li&gt; 的所有实例&lt;ul&gt;&lt;/ul&gt; 之间应该保持不变:

<ol>
    ##li##some text##/li##
    ##li##some <strong>more</strong> text##/li##
    ##li##some more text##/li##
</ol>
<ul>
    <li>even more text</li>
    <li>...</li>
</ul>

虽然这主要是一个正则表达式问题,但如果我在存储过程中使用 Oracle XE 11g2 上的 Oracle REGEXP_REPLACE 函数感兴趣的话。

我很想发布到目前为止我尝试过的内容,但老实说,我完全迷失了这一点。

这个操作分两遍就可以了:

l_html_new :=
REGEXP_REPLACE(
  l_html_old
, '<regex1 here>'
, '##li##'
);

l_html_new :=
REGEXP_REPLACE(
  l_html_new 
, '<regex2 here>'
, '##/li##'
);

更新:

@cfqueryparam,您的解决方案很有趣,因为它似乎完全符合我在 JS 中的需要。但是,我无法让它在 Oracle 中工作。 这是我所拥有的:

declare
  --
  c_crlf char(2) := chr(13)||chr(10);
  --
  l_html_old varchar2(4000);
  l_html_new varchar2(4000);
  l_pattern  varchar2(400);
  --
begin
  l_html_old :=   
      '<ol>'||c_crlf
  ||    '<li>some text</li>'||c_crlf
  ||    '<li>some <strong>more</strong> text</li>'||c_crlf
  ||    '<li>some more text</li>'||c_crlf
  ||  '</ol>'||c_crlf
  ||  '<ul>'||c_crlf
  ||    '<li>even more text</li>'||c_crlf
  ||    '<li>...</li>'||c_crlf
  ||  '</ul>'
  ;
  --
  l_pattern := '<(li)>(.*?)<(\/li)>([^>]*)(?=(<li>.*?<\/li>[^>]*)*(?:[^>]*<\/ol>))';
  --
  l_html_new := 
    REGEXP_REPLACE(
      l_html_old                  --source_string
    , l_pattern                   --pattern
    , '##$1##$2##$3##$4'          --replace_string
    , 1                           --position
    , 0                           --occurrence
    , 'im'                        --match_parameter
  );
  --
  dbms_output.put_line(l_html_new);
  --
end;

这只是输出没有替换的原始字符串。 反向引用可能存在问题,但我认为这并不重要。由于根本没有发生替换,我认为没有任何匹配。

我会尝试找出JS和Oracle在处理上的区别。

【问题讨论】:

    标签: sql regex oracle plsql tags


    【解决方案1】:

    我没有用于测试的 ORACLE 数据库,但我可以用 javascript 演示一些您可以利用的东西。

    演示:http://jsfiddle.net/knjv9zjp/1/

    <(li)>(.*?)<(\/li)>([^>]*)(?=(<li>.*?<\/li>[^>]*)*(?:[^>]*<\/ol>))
    

    我确实想到您可能想要考虑 LI 标记的属性,这很容易。

    此版本将捕获属性,并将它们放入开头的哈希中

    <(li[^>]*)>(.*?)<(\/li)>([^>]*)(?=(<li>.*?<\/li>[^>]*)*(?:[^>]*<\/ol>))
    

    此版本将识别可能存在的属性,而不捕获它们

    <(li)[^>]*>(.*?)<(\/li)>([^>]*)(?=(<li>.*?<\/li>[^>]*)*(?:[^>]*<\/ol>))
    

    【讨论】:

    • @silentsurfer sqlfiddle 已关闭 atm,但我会在它恢复时尝试提供更多帮助。
    • 谢谢,非常感谢您在这里帮助我。
    • @silentsurfer 试试&lt;(li)&gt;(.*?)&lt;(\/li)&gt;([^&gt;]*)((&lt;li&gt;.*?&lt;\/li&gt;[^&gt;]*)*(?:[^&gt;]*&lt;\/ol&gt;)),你的替换字符串是##$1##$2##$3##$4$5 Oracle 正则表达式似乎不支持环视。恐怕这可能只取代第一次迭代。
    • 我偶然发现了这篇文章 (stackoverflow.com/questions/16702672/…),指出了一个关于 Oracle 中操作员贪婪的错误。你认为这可能是一个问题吗?
    • @silentsurfer 读起来很有趣!当小提琴起死回生时,我会用棍子和支架戳东西。
    【解决方案2】:

    我认为你需要的只是简单的 Replace():

    SELECT REPLACE(
    '<ol>
      <li>some text</li>
      <li>some <strong>more</strong> text</li>
      <li>some more text</li>
    </ol>
    <ul>
      <li>even more text</li>
      <li>...</li>
     </ul>', '<li>', '###li###')
    FROM dual
    /
    

    输出:

    <ol>
       ###li###some text</li>
       ###li###some <strong>more</strong> text</li>
       ###li###some more text</li>
    </ol>
    <ul>
       ###li###even more text</li>
       ###li###...</li>
    </ul>
    

    【讨论】:

    • 他特别不想修改&lt;ul&gt; 中的&lt;li&gt;s。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2014-05-08
    • 2019-06-21
    • 2012-05-21
    相关资源
    最近更新 更多