【问题标题】:Regular Expression replacing substring正则表达式替换子字符串
【发布时间】:2020-09-25 11:57:57
【问题描述】:

在表格中它是可用的列,如“ABCURLCBSURLDMSURLWER”。 URL 在该列中重复。我想检索两个 URL 之间的语句,如下所示。

Column
------
CBS
DMS

我写了如下查询,但我写的查询没有检索到我想要的结果。

SELECT 
REGEXP_SUBSTR((SELECT REPLACE(REPLACE('ABCURLCBSURLDMSURLALI','URL',','),'ABC',',') AS AB FROM 
DUAL),'[^,]+',1,LEVEL) AS AB
FROM
DUAL
CONNECT BY
REGEXP_SUBSTR((SELECT REPLACE(REPLACE('ABCURLCBSURLDMSURLWER','URL',','),'ABC',',') AS AB FROM 
DUAL),'[^,]+',1,LEVEL)
IS NOT NULL;

AB
---
CBS
DMS
WER

我该如何解决这个问题?

【问题讨论】:

  • 只是想知道,为什么 URL 是这样存储的?
  • 我不得不用重复的东西来举个例子,所以我用了它:))。

标签: sql oracle substring


【解决方案1】:

尝试这样的查询。复制您的解决方案以将 URL 文本替换为 , 使正则表达式更容易拆分字符串。

更新查询

WITH some_data (ab) AS (SELECT 'ABCURLCBSURLDMSURLWER' FROM DUAL)
SELECT REGEXP_SUBSTR (REPLACE (sd.ab, 'URL', ','),
                      '[^,]+',
                      1,
                      lines.COLUMN_VALUE)    AS ab
  FROM some_data  sd,
       TABLE (CAST (MULTISET (    SELECT LEVEL     AS level_num
                                    FROM DUAL
                              CONNECT BY INSTR (sd.ab,
                                                'URL',
                                                1,
                                                LEVEL) > 0) AS SYS.odciNumberList)) lines
 WHERE lines.COLUMN_VALUE > 1;

输出

    AB
______
CBS
DMS

【讨论】:

  • 很遗憾,结果是错误的。它也检索了 ​​ABC 和 WE 作为该查询的结果。
  • @EJEgyed,OP 只需要 URL 之间的值,即 CBSDMS
  • 这是错误的(除了它不符合问题的要求)因为[^(URL)] 匹配任何一个不是左圆括号(UR 的字符或L 或右圆括号)。因此,如果您的输入为 'URL(LUR)(LUR)URL',那么您将找不到匹配的字符。
  • 我已经修复了查询,所以它现在应该返回正确的结果。
  • 如果字符串是'ABCURLCB,SURLDMSURLWER',这只会返回CBS,而不是CB,SDMSdb<>fiddle
【解决方案2】:

还有一个选择;查看代码中的 cmets:

SQL> with test (col) as
  2    -- sample data
  3    (select 'ABCURLCBSURLDMSURLWER' from dual),
  4  rpl as
  5    -- replace URL with a semi-colon (a single/simple delimiter)
  6    (select replace(col, 'URL', ';') col
  7     from test
  8    ),
  9  rmv as
 10    -- remove everything in front of the 1st delimiter and everything after the last delimiter
 11    (select substr(col, instr(col, ';') + 1,
 12                        instr(col, ';', -1, 1) - instr(col, ';') - 1) val
 13     from rpl
 14    )
 15  select regexp_substr(val, '[^;]+', 1, level) result
 16  from rmv
 17  connect by level <= regexp_count(val, ';') + 1;

RESULT
--------------------
CBS
DMS

SQL>

【讨论】:

  • 如果字符串是'ABCURLCB;SURLDMSURLWER',则返回 3 行而不是 2 行。db<>fiddle
  • 当然,@MT0,但示例数据没有说明在字符串中包含分号。另一方面,它也没有说明不包含它:)
【解决方案3】:

您不需要正则表达式,只需使用简单的字符串函数即可:

WITH bounds ( id, value, start_pos, end_pos ) AS (
  SELECT id,
         value,
         INSTR( value, 'URL', 1, 1 ) + 3,
         INSTR( value, 'URL', 1, 2 )
  FROM   table_name
UNION ALL
  SELECT id,
         value,
         end_pos + 3,
         INSTR( value, 'URL', end_pos + 3, 1 )
  FROM   bounds
  WHERE  end_pos > 0
)
SELECT id,
       start_pos,
       SUBSTR( value, start_pos, end_pos - start_pos ) AS url
FROM   bounds
WHERE  end_pos > 0
ORDER BY id, start_pos;

所以,对于样本数据:

CREATE TABLE table_name ( id, value ) AS
SELECT 1, 'ABCURLCBSURLDMSURLWER' FROM DUAL UNION ALL
SELECT 2, 'ABCURLURLDEFURLGHIURL' FROM DUAL;

这个输出:

身份证 | START_POS |网址 -: | --------: | :--- 1 | 7 |哥伦比亚广播公司 1 | 13 |管理系统 2 | 7 | 2 | 10 |国防军 2 | 16 |全球健康指数

db小提琴here


选项 2

如果你确实想使用正则表达式,那么你可以使用:

SELECT t.id,
       x.COLUMN_VALUE AS url
FROM   table_name t
       CROSS APPLY TABLE(
         CAST(
           MULTISET(
             SELECT REGEXP_SUBSTR(
                      t.value,
                      '(.*?)URL',
                      INSTR( t.value, 'URL' ) + 3,
                      LEVEL,
                      NULL,
                      1
                    )
              FROM  DUAL
              CONNECT BY
                     LEVEL <= REGEXP_COUNT(
                                t.value, '(.*?)URL', INSTR( t.value, 'URL' ) + 3
                              )
           )
           AS SYS.ODCIVARCHAR2LIST
         )
       ) x;

对于相同的测试数据,输出:

身份证 |网址 -: | :--- 1 |哥伦比亚广播公司 1 |管理系统 2 | 2 |国防军 2 |全球健康指数

db小提琴here

【讨论】:

  • 如果您的 test_data 表中包含多于一行,则选项 2 将不起作用,因为您会得到重复的数据。
  • @EJEgyed OP 只有一行输入。然而,这是一个简单的修复,所以我已经更新它来处理多行。只需将查询和CROSS APPLY/CROSS JOIN 带到表集合表达式内的多行输入表中。
猜你喜欢
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
相关资源
最近更新 更多