Oracle 正则表达式,如果字符串以数字开头,则在开头查找长度为 3 的数字。否则,在末尾找到 3 位数长度的数字
Oracle regexp, Find a number length of 3 in the beginnning, if the string begins with a number. Else, find number with 3 digit length at the end
我已经使用了 case 语句,但仍然不起作用。我该如何解决这个问题。
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;
查询结果:
STR NUM_VAL
--------------------------------------------
141 - Uxsdfasd Zebasdased ABC3 141
639 - xadfa dfdsa euwere (15-30Min) 530
AB/NCDSDFsd - 218 218
如果字符串以 3 个连续数字集开头,那么我需要前 3 个数字集。如果字符串以字母开头,那么我需要在字符串末尾设置 3 位数字。
预期输出:
STR NUM_VAL
--------------------------------------------
141 - Uxsdfasd Zebasdased ABC3 141
639 - xadfa dfdsa euwere (15-30Min) 639
AB/NCDSDFsd - 218 218
据我了解你的问题,这将是一个解决方案:
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
在数字和结束锚之间使用非贪婪量词或....反向函数
我使用非贪婪量词方法(第 23 行),但它似乎主要起作用,因为第一个量词是贪婪的。
我使用锚点来匹配整个字符串。我将匹配 "non-end of line character", ., 放在一个子表达式中,并在字符串末尾使用非贪婪量词 *? (零个或多个)。
非贪婪量词在 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
重新制定的问题可以解决,例如,如下:
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 位数字。
我已经使用了 case 语句,但仍然不起作用。我该如何解决这个问题。
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;
查询结果:
STR NUM_VAL
--------------------------------------------
141 - Uxsdfasd Zebasdased ABC3 141
639 - xadfa dfdsa euwere (15-30Min) 530
AB/NCDSDFsd - 218 218
如果字符串以 3 个连续数字集开头,那么我需要前 3 个数字集。如果字符串以字母开头,那么我需要在字符串末尾设置 3 位数字。 预期输出:
STR NUM_VAL
--------------------------------------------
141 - Uxsdfasd Zebasdased ABC3 141
639 - xadfa dfdsa euwere (15-30Min) 639
AB/NCDSDFsd - 218 218
据我了解你的问题,这将是一个解决方案:
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
在数字和结束锚之间使用非贪婪量词或....反向函数
我使用非贪婪量词方法(第 23 行),但它似乎主要起作用,因为第一个量词是贪婪的。
我使用锚点来匹配整个字符串。我将匹配 "non-end of line character", ., 放在一个子表达式中,并在字符串末尾使用非贪婪量词 *? (零个或多个)。
非贪婪量词在 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
重新制定的问题可以解决,例如,如下:
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 位数字。