0

我正在努力使用正则表达式替换解决方案,该解决方案将删除 VARCHAR2 字段中引号之间的所有文本,即使这些引号之间的文本也引用了文本例如文本:

'text start 'text inside' text end' leftover 'some other text'

正则表达式替换后应包含: leftover

我想出的是这段代码:

with tbl as (
  select
    '''text start ''text inside'' text end'' leftover ''some other text''' as str
    ,'\''(.*?)\''' as regex
  from dual
)
select
  tbl.str as strA
  ,regexp_replace(tbl.str,tbl.regex, '') as strB
from tbl; 

但子引号之间的文字仍然存在。

甚至可以使用正则表达式来实现这一点,还是应该在某个循环中拆分和分析内容?一个理想的解决方案是如果它可以处理引用文本中引用文本的无限级别出现。

4

2 回答 2

1

一个理想的解决方案是如果它可以处理引用文本中引用文本的无限级别出现。

使用单个正则表达式是不可能的。
Oracle 中既不提供递归正则表达式,也不提供递归捕获缓冲区。


UPD:
但它可以通过 SQL 来完成:

with tbl as (
  select
    '''text start ''text inside'' text end'' leftover ''some other text''' 
    as str
  from dual
)
select
  listagg(text) within group (order by n) 
from 
  (
    select 
      n,
      sum(decode(regexp_replace(str, '^(.*?([<>])){'||n||'}.*$', '\2'),
        '<', 1, '>', -1, 0)) over (order by n) as nest,
      regexp_replace(str, '^(.*?[<>]){'||n||'}([^<>]*).*$', '\2') as text
    from 
      ( select regexp_replace(regexp_replace(str, '(\s|^)''', '\1<'), 
          '''(\s|$)', '>\1') as str from tbl ), 
      ( select level-1 as n from dual 
        connect by level-1 <= (select regexp_count(str, '''') from tbl) )
  )
where nest = 0

小提琴

于 2013-04-15T12:46:40.687 回答
1

尝试

, '^[^'']*(''.*'')[^'']*$' as regex

警告:这将愚蠢地捕获捕获组 1 中测试文本中第一次和最后一次出现单引号之间的所有内容,包括最外面的引号本身。特别是它不检查正确的嵌套。

更重要的是你的替换 expr 会更复杂:

, CASE WHEN REGEXP_INSTR(test, regex) > 0
     THEN REPLACE ( test, REGEXP_REPLACE(test, regex, '\1'), '' )
     ELSE test
  END

如果正则表达式匹配,则首先提取捕获组以用于普通替换(这是因为保证匹配的部分是最大的)。

重要提示:该解决方案不会在您提供的特定上下文中产生所需的结果。但是,您不能更好地使用 plsqlregexp函数,因为 oracle 正则表达式引擎不提供扩展来表达模式中的递归(例如 pcre 所做的)。您需要此工具来解决嵌套结构(即执行平衡计数)。

于 2013-04-15T12:10:59.113 回答