【问题标题】:Oracle Regexp - substr by multiple spaces but not single spaceOracle Regexp - substr 由多个空格但不是单个空格
【发布时间】:2017-03-25 00:27:34
【问题描述】:

假设我有一个字符串-

"a   b      cc  d d  e"

我希望能够做到

regexp_substr('a   b      cc  d d  e', ??, 1, 4)

并让它返回“d d”。

我使用“[^ ]+”作为我的模式,但它分割了我不想要的单个空格。

【问题讨论】:

  • 这个不清楚。你想返回什么?第四次出现(一个或多个空格),加上两边的非空格字符的完整块?

标签: sql regex oracle plsql


【解决方案1】:

这个可以解决问题:

select regexp_substr(str, '([^ ]([ ]?[^ ])*)',1, 4)

如果你想解析出所有谨慎的值,你可以使用这个:

with sample_data as (
  select 'a   b      cc  d d  e' str from dual union all
  select ' a   b      cc  d dd d  e' str from dual
)
, recurse(str, seq, nxt, tok) as (
select str
     , 1
     , regexp_instr (str, '[ ]{2,}',1,1,1)
     , regexp_substr(str, '([^ ]([ ]?[^ ])*)',1, 1)
 from sample_data
union all
select str
     , seq+1
     , regexp_instr(str, '[ ]{2,}',nxt,1,1)
     , regexp_substr(str, '([^ ]([ ]?[^ ])*)',nxt, 1)
 from recurse
 where nxt > 0
)
select * from recurse order by str, seq;

STR                              SEQ        NXT TOK                     
------------------------- ---------- ---------- -------------------------
 a   b      cc  d dd d  e          1          6 a                        
 a   b      cc  d dd d  e          2         13 b                        
 a   b      cc  d dd d  e          3         17 cc                       
 a   b      cc  d dd d  e          4         25 d dd d                   
 a   b      cc  d dd d  e          5          0 e                        

a   b      cc  d d  e              1          5 a                        
a   b      cc  d d  e              2         12 b                        
a   b      cc  d d  e              3         16 cc                       
a   b      cc  d d  e              4         21 d d                      
a   b      cc  d d  e              5          0 e                        

 10 rows selected 

【讨论】:

    【解决方案2】:

    假设您正在寻找一个或多个连续空格的第四次出现,并且您希望返回该 PLUS 周围的非空格字符(并在字符串的开头或结尾允许一个或多个空格,在在这种情况下,结果在那一侧不会有非空格字符):

    with
         inputs ( str, occ ) as (
           select 'a   b      cc  d d  e', 4 from dual
         )
    select regexp_substr(str, '([^ ]+|^)[ ]+', 1, occ) || 
              regexp_substr(str,'[ ]+([^ ]+|$)', 1, occ, null, 1) as token
    from inputs
    ;
    

    具体来说,这将为occ 的值 1、2、3、4、5 生成以下输出:

    'a b''b cc''cc d''d d''d e'

    请注意,一旦找到一个匹配项,就会从已经找到的匹配项之后的字符开始搜索下一个匹配项。在我对问题的解释中,非空格字符包含在重叠的候选匹配中,因此不可能(我不认为)在一次 regexp_substr 中执行此操作。

    我在顶部的 CTE 中输入字符串和出现 (4);这是设置测试数据的一部分,而不是解决方案的一部分。

    【讨论】:

      【解决方案3】:

      我认为这会做你想要的:

      select regexp_substr(col, '([^ ]*[ ]?[^ ]+)+', 1, 4)
      

      【讨论】:

      • 如果将参数 4 替换为 2,则此解决方案将产生结果 'b '(即,某事物的“第二次出现”是 'b '。很难理解这与问题陈述。
      • ...但答案被接受了,所以我肯定错过了一些东西! :-)
      • regexp_substr(col, '\S( ?\S)*', 1, 4) 会更正确
      猜你喜欢
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多