首页 > 解决方案 > 无法在 oracle 中使用正则表达式 substr 获得模式的第二次出现

问题描述

SELECT
  REGEXP_SUBSTR('500 ,Oracle 1234,123Parkway123aa 123, 768Redwood Shores, CA,',
                '\d+,\d+[^,]+,',1,2) "REGEXPR_SUBSTR"
  FROM DUAL;

期望是获得第二次出现的输出,123, 768Redwood Shores, 但是我怎么能正确地获得第一次出现的模式但不是第二次,我很理解为什么?谁能给我解释一下,谢谢。

标签: sqloracle

解决方案


[TL;DR]正则表达式找不到重叠匹配。


第一场比赛:

SELECT REGEXP_SUBSTR(
         '500 ,Oracle 1234,123Parkway123aa 123, 768Redwood Shores, CA,',
         '\d+,\d+[^,]+,',
         1,
         1
       ) "REGEXPR_SUBSTR"
FROM   DUAL;

是:

1234,123Parkway123aa 123,

它将在第一场比赛之后寻找第二场比赛(不与第一场比赛重叠);所以将在子字符串中寻找第二个匹配项:

' 768Redwood Shores, CA,'

并没有找到任何东西。

即使正则表达式确实支持重叠匹配(它们不支持),它也不会找到任何东西,因为逗号后面有一个空格,您的模式不匹配。

这将允许重叠匹配(但要复杂得多并且不是单个函数):

SQL小提琴

查询 1

WITH data ( value ) AS (
  SELECT '500 ,Oracle 1234,123Parkway123aa 123, 768Redwood Shores, CA,'
  FROM   DUAL
),
pos ( value, match, pos, lvl ) AS (
  SELECT value,
         REGEXP_SUBSTR( value, '\d+,\s*\d+[^,]+?(\d*),', 1, 1 ),
         REGEXP_INSTR( value, '\d+,\s*\d+[^,]+?(\d*),', 1, 1, 0, NULL, 1 ),
         1
  FROM   data
UNION ALL
  SELECT value,
         REGEXP_SUBSTR( value, '\d+,\s*\d+[^,]+?(\d*),', pos, 1 ),
         REGEXP_INSTR( value, '\d+,\s*\d+[^,]+?(\d*),', pos, 1, 0, NULL, 1 ),
         lvl + 1
  FROM   pos
  WHERE  pos > 0
)
SELECT match
FROM   pos
WHERE  pos > 0
AND    lvl = 2

结果

|                   MATCH |
|-------------------------|
| 123, 768Redwood Shores, |

推荐阅读