Oracle正则表达式,如果字符串以数字开头,则在开头查找数字长度3。否则,找到末尾有3位数字的数字

时间:2018-06-20 18:52:16

标签: oracle regexp-replace

我使用了case语句,但仍然无法正常工作。我该怎么解决。

 d   m      k
 3  33  2863311531
 5  34  3435973837
 6  34  2863311531
 9  35  3817748708
10  35  3435973837
11  35  3123612579
12  35  2863311531
13  35  2643056798
15  35  2290649225
17  36  4042322161

查询结果:

WITH tst
AS
(
  SELECT '639 - xadfa dfdsa euwere (15-30Min)' str FROM DUAL
  UNION
  SELECT 'AB/NCDSDFsd - 218' FROM DUAL
  UNION
  SELECT '141 - Uxsdfasd Zebasdased ABC3' FROM DUAL
)
SELECT 
  str,
  CASE 
    WHEN LENGTH(TRIM(SUBSTR(TRIM(REGEXP_REPLACE(str, '([^[:digit:] ])', '')),-3,3))) = 3        
    THEN TRIM(SUBSTR(TRIM(REGEXP_REPLACE(str, '([^[:digit:] ])', '')),-3,3))
    ELSE
     CASE 
      WHEN LENGTH(TRIM(SUBSTR(TRIM(REGEXP_REPLACE(str, '([^[:digit:] ])', '')),1,3))) = 3
      THEN TRIM(SUBSTR(TRIM(REGEXP_REPLACE(str, '([^[:digit:] ])', '')),1,3))
      ELSE NULL
    END
  END num_val
FROM tst;  

如果字符串以3个连续数字集开头,那么我需要第一个3位数字集。如果字符串以字母开头,那么我需要在字符串末尾设置3位数字。    预期输出:

   STR                                  NUM_VAL
   --------------------------------------------
   141 - Uxsdfasd Zebasdased ABC3       141
   639 - xadfa dfdsa euwere (15-30Min)  530
   AB/NCDSDFsd - 218                    218

3 个答案:

答案 0 :(得分:2)

重新设计的问题可以解决,例如,如下:

WITH tst
AS
(
  SELECT '639 - xadfa dfdsa euwere (15-30Min)' str FROM DUAL UNION ALL
  SELECT 'AB/NCDSDFsd - 218'                       FROM DUAL UNION ALL
  SELECT 'dsafas 123 COMP - 751'                   FROM DUAL UNION ALL
  SELECT '141 - Uxsdfasd Zebasdased ABC3'          FROM DUAL
)
select str, regexp_substr(str, '(^\d{3}|\d{3}$)') as num
from   tst;

STR                                 NUM                                
----------------------------------- -------------------
639 - xadfa dfdsa euwere (15-30Min) 639                
AB/NCDSDFsd - 218                   218
dsafas 123 COMP - 751               751                
141 - Uxsdfasd Zebasdased ABC3      141

正则表达式是一个交替。 ^$是锚点-它们要求片段分别位于输入字符串的开头和结尾。 ( ... | ... )表示找到第一个替代方案,如果找不到,则找到第二个替代方案。 \d{3}恰好表示3位数字。

答案 1 :(得分:0)

据我所知,这是一个解决方案:

WITH tst
AS
(
  SELECT '639 - xadfa dfdsa 456 euwere (15-30Min)' str FROM DUAL
  UNION
  SELECT 'AB/NCDSDFsd - 218' FROM DUAL
  UNION
  SELECT '141 - Uxsdfasd Zebasdased ABC3' FROM DUAL
)
select str,
   regexp_substr(str, '[[:digit:]]{3}', 1, regexp_count(str, '[[:digit:]]{3}')) as num_val
from tst;


STR                                          NUM_VAL 
-------------------------------------------  -----------
141 - Uxsdfasd Zebasdased ABC3               141
639 - xadfa dfdsa 456 euwere (15-30Min)      456
AB/NCDSDFsd - 218                            218

答案 2 :(得分:0)

在数字和末尾锚点之间使用非贪婪量词,或者使用....反向功能

我使用非贪婪量词方法(第23行),但是它似乎主要是因为第一个量词是贪心。

我使用锚来匹配整个字符串。我将匹配项“非行字符”放在子表达式中,并在字符串的末尾使用非贪婪量词*? (零个或多个)。

非贪婪量词在Oracle 12.1(我正在使用)中并不总是有效。

方案b只是使用反向函数2x(第24行)。

SCOTT@db>WITH tst AS (
  2      SELECT
  3          '141 - Uxsdfasd Zebasdased ABC3 141 639 - xadfa dfdsa euwere (15-30Min) 639 AB/NCDSDFsd - 2184 4  5' smple
  4      FROM
  5          dual
  6      UNION ALL
  7      SELECT
  8          '639 - xadfa dfdsa euwere (15-30Min)'
  9      FROM
 10          dual
 11      UNION ALL
 12      SELECT
 13          'AB/NCDSDFsd - 218'
 14      FROM
 15          dual
 16      UNION ALL
 17      SELECT
 18          '141 - Uxsdfasd Zebasdased ABC3'
 19      FROM
 20          dual
 21  ) SELECT
 22      smple,
 23      regexp_substr(smple,'^(.)*(\d{3})(.)*?$',1,1,NULL,2) nongreedy,
 24      reverse(regexp_substr(reverse(smple),'(\d{3})',1,1,NULL,1) ) rev_fun
 25    FROM
 26      tst;
SMPLE                                                                                                NONGREEDY   REV_FUN
141 - Uxsdfasd Zebasdased ABC3                                                                       141         141
141 - Uxsdfasd Zebasdased ABC3 141 639 - xadfa dfdsa euwere (15-30Min) 639 AB/NCDSDFsd - 2184 4  5   184         184
639 - xadfa dfdsa euwere (15-30Min)                                                                  639         639
AB/NCDSDFsd - 218                                                                                    218         218