基本上,我在 PL/SQL 中有一个输入字符串,如下所示:
input varchar2(100) := R985AD5768N2
该字符串由多个信息组成,每个信息前面都有某个前缀,并将每个块连接起来。前缀列表是可变的,在本例中为
R
、D5
、G
和 N
。信息可以包含数字和字符,只要没有作为前缀的字符序列即可。此外,某些前缀可能不一定出现在输入字符串内。
我的目标是使用 REGEXP_SUBSTR 按前缀过滤每个块的信息,因此从上面的示例中得到以下结果:
R -> 985A
D5 -> 768
G -> NULL
N -> 2
我的总体想法是分别使用
'R([^R|D5|G|N]+)(R|D5|G|N)?'
形式的模式作为 R
,这意味着我要求我的序列以字符 R 开头,然后使用所有后续字符直到下一个前缀(或字符串末尾)到达了。使用 REGEXP_SUBSTR 的 subexpr 参数,我可以直接选择第二部分,即我正在寻找的信息。
我尝试了几种方法:
REGEXP_SUBSTR(input, 'R([^R|D5|G|N]+)(R|D5|G|N)?', 1, 1, 'c', 1) -- and other prefixes accordingly
很好,除了
R
结果只有 98,我猜是因为 5 出现在 D5 前缀中。
REGEXP_SUBSTR(input, 'R(\w+)(R|D5|G|N)', 1, 1, 'c', 1)
使用正向方法,它将选择最长的方法,这意味着输入在其各自的前缀之后的全部剩余部分。
我尝试了其中的几种变体,例如替换一些括号,但似乎一个关键缺陷仍然是
D5
前缀在其各自的括号中未被识别为文字。
我看到一些方法使用一些前瞻参数,但遗憾的是,据我所知,这些方法不受支持。
关于如何澄清这一点有什么想法吗?
您可以使用递归查询并仅查找前缀并找到它们的开始和结束位置,然后后缀将是它们之间的子字符串。
WITH sample_data (value) AS (
SELECT 'R985AD5768N2' FROM DUAL
),bounds (value, sspos, sepos, espos, eepos) AS (
SELECT value,
1,
2,
REGEXP_INSTR(value, 'R|G|N|D5', 2, 1, 0),
REGEXP_INSTR(value, 'R|G|N|D5', 2, 1, 1)
FROM sample_data
WHERE value LIKE 'R%'
UNION ALL
SELECT value,
espos,
eepos,
REGEXP_INSTR(value, 'R|G|N|D5', eepos, 1, 0),
REGEXP_INSTR(value, 'R|G|N|D5', eepos, 1, 1)
FROM bounds
WHERE eepos > 0
)
SELECT SUBSTR(value, sspos, sepos - sspos) AS prefix,
CASE WHEN espos = 0
THEN SUBSTR(value, sepos)
ELSE SUBSTR(value, sepos, espos - sepos)
END AS suffix
FROM bounds
哪个输出:
前缀 | 后缀 |
---|---|
R | 985A |
D5 | 768 |
N | 2 |