1

如何使用 REGEXP_SUBSTR 在 Oracle中获取我想要的这些数据

SPRINTMVNO_PM_CDR_IWIRELESS_20121110_0813.csv get '08'in last four digits
RK_IPDR_RKMSG2_0043722_DT_20121113162710.txt  get '0043722' in the middle(between'_')
wireless_201211120015_201211120515            get '0515' (last four digits)

我已经尝试了很多次,但有些表达式在 PHP 或其他语言中可以正常工作,但在 ORACLE 中不能正常工作。也许语法不同。

例如:我可以使用第二个 /(?<=_)[0-9]*(?=_)/来获取 php 中的数字,但这在 Oracle 中不起作用。
我试过了

SELECT REGEXP_SUBSTR('RK_IPDR_RKMSG2_0043722_DT_20121113162710.txt','(?<=_)[0-9]*(?=_)') 
  FROM dual;

没有输出。所以不是两条斜线的问题

这个问题的另一种表述是“如何使用 Oracle 的正则表达式在字符之间获取内容或以字符开头但不包含它?”

我知道我可以通过使用字符串函数轻松获取这些数据,问题是要处理大量不同的字符串,每个字符串都有不同的数据要检索。所以我想将模式存储到数据库中,并使用一个 regexp_substr 来获取所有数据。否则我需要对这些规则进行硬编码。

4

3 回答 3

1

Oracle 从业者在没有正则表达式的情况下存活了多年,因为 Oracle 提供了一些简单的字符串函数,我们可以将它们组合起来进行一些漂亮的操作。

例如,要查找字符串中最后一个下划线之后的前两个字符,请使用 SUBSTR() 和 INSTR(),如下所示:

with t as (select 'SPRINTMVNO_PM_CDR_IWIRELESS_20121110_0813.csv' str from dual)
select substr(str, instr(str, '_', -1)+1, 2)
from t
/

注意 INSTR() 调用有一个负偏移量,从后面开始计数。获取字符串的最后四个字符使用相同的技巧:

with t as (select 'iwireless_201211120015_201211120515' str from dual)
select substr(str, -4)
from t
/

识别下划线后跟数字后跟下划线的模式的最简单方法是使用正则表达式,但我们可以使用 TRIM() 从结果中删除下划线。

with t as (select 'RK_IPDR_RKMSG2_0043722_DT_20121113162710.txt' str from dual)
select trim('_' from regexp_substr(str, '_([0-9]+)_'))
from t
/

这是一个 SQL Fiddle来证明这些技术是有效的。

Oracle 有大量的函数,这些函数在文档中进行了描述。 了解更多


“请忽略这些情况,我只需要一个解决方案'如何使用 Oracle 的正则表达式在字符之间获取内容或以字符开头但不包含它?'”

有一种方法可以从结果的开头或结尾排除字符,即将搜索模式分解为子表达式。这将适用于您提供的字符串,因为我们可以将前导和尾随下划线与所需数字分开。不幸的是,subexpressions参数是REGEXP_SUBSTR() 签名中的最后一个参数,并且由于 SQL 函数不接受命名参数,这意味着我们必须显式传递所有其他参数的默认值。

无论如何,此调用将返回第二个子表达式,即所需的字符串0043722

with t as (select 'RK_IPDR_RKMSG2_0043722_DT_20121113162710.txt' str from dual)
select regexp_substr(str, '(_)([0-9]+)(_)', 1,1,'i',2)
from t
/

用例确实很重要。REGEXP 函数的执行速度比更简单的等效函数慢。在 10gR2 中,REGEXP_SUBSTR() 至少比 SUBSTR() 慢一个数量级。当搜索大量字符串时,差异很明显,而当这个数字变成数百万时,差异就很明显了(披露:最近的痛苦)。

于 2012-11-17T08:42:20.940 回答
1

正则表达式周围的前导和尾随斜杠与 regex 无关

它们是 perl/javascript 语言的产物。

尝试使用斜线

于 2012-11-17T00:20:30.257 回答
0

Oracle 使用 POSIX ERE(扩展正则表达式) - 一个明显的例外是它添加了反向引用。但是 POSIX ERE 非常有限——它只需要很少的东西。尝试以下正则表达式:

/([0-9]{2}80|[0-9]80[0-9]|80[0-9]{2})$/

这会让你在最后四位数中得到 80。

/0515$/

这会让你得到 0515 作为最后四位数字。

现在,我从来没有使用过 Oracle,所以我不知道你是否需要分隔符,但这两个会起作用。中间的有点棘手。如果您可以只接受“是的,它就在那里”,那么您应该可以侥幸逃脱

/_0043722_/

但是如果您需要提取它,您应该能够找到一些修剪功能,让您指定要修剪的内容。你不能在 Oracle 中使用正则表达式。

哦,如果您需要将所有这三个组合成一个正则表达式:

/([0-9]{2}80|[0-9]80[0-9]|80[0-9]{2}|0515)$|_0043722_/

如果您将来需要正则表达式参考,请试试这个网站

于 2012-11-17T01:59:39.847 回答