如何在第 n 次出现管道“|”后获取字符或字符串ORACLE 中使用 REGULAR_EXPRESSION 的符号?
Posted
技术标签:
【中文标题】如何在第 n 次出现管道“|”后获取字符或字符串ORACLE 中使用 REGULAR_EXPRESSION 的符号?【英文标题】:How to get character or string after nth occurrence of pipeline '|' symbol in ORACLE using REGULAR_EXPRESSION? 【发布时间】:2017-07-23 15:55:09 【问题描述】:ORACLE 中管道|
符号第n 次出现后获取字符或字符串的正则表达式查询是什么?例如我有两个字符串如下,
Jack|Sparrow|17-09-16|DY7009|Address at some where|details
|Jack|Sparrow|17-09-16||Address at some where|details
我想要'DY7009',它位于从第一个位置开始的第三个管道符号之后,那么正则表达式查询将是什么?在第二个字符串中假设第一个位置有|
符号,那么我想要第四个字符串,如果没有值那么它应该给出 NULL 或 BLANK 值。
select regexp_substr('Jack|Sparrow|17-09-16|DY7009|Address at some where|details'
,' ?? --REX Exp-- ?? ') as col
from dual;
结果 - DY7009
select regexp_substr('Jack|Sparrow|17-09-16|DY7009|Address at some where|details'
,' ?? --REX Exp-- ?? ') as col
from dual;
结果 - '' 或(即 NULL)
那么正则表达式应该是什么?请帮忙。提前谢谢你
新的更新编辑 ---
谢谢大家!!谢谢你们的回答!!我想,我没有问对。我只想要一个正则表达式在第 n 次出现管道符号后获取“字符串/字符串”。我不想替换任何字符串,所以只有 regexp_substr 可以完成这项工作。
----> 如果 'Jack|Sparrow|SQY778|17JULY17||00J1' 是一个字符串
我想在这里找到第二个管道符号之后的字符串值,答案是 SQY778。如果我想在第三个管道符号之后找到字符串,那么答案将是 17JULY17。如果我想在第 4 个管道符号之后找到值,那么它应该给出 BLANK 或 NULL 值,因为在第 4 个管道符号之后没有任何内容。如果我想找到字符串第 5 个符号,那么我只会替换正则表达式中的一位数字,即 5,结果我会得到 00J1。
【问题讨论】:
在下面检查我的答案。请注意,在您提供的第二个查询中,使用的字符串与开头提到的不同。我假设你需要||被视为空白(NULL) 检查我的答案的最后编辑。它应该可以工作。如果您有任何不工作的情况,请告诉我。 【参考方案1】:给你。将 regexp_substr() 的第 4 个参数替换为所需字段的编号。
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select regexp_substr(str, '(.*?)(\||$)', 1, 4, NULL, 1) field_4
from tbl;
FIELD_4
--------
DY7009
SQL>
列出所有字段:
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select regexp_substr(str, '(.*?)(\||$)', 1, level, NULL, 1) split
from tbl
connect by level <= regexp_count(str, '\|')+1;
SPLIT
-------------------------
Jack
Sparrow
17-09-16
DY7009
Address at some where
details
6 rows selected.
SQL>
因此,如果您想要选择可以使用的字段:
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select
regexp_substr(str, '(.*?)(\||$)', 1, 1, NULL, 1) first,
regexp_substr(str, '(.*?)(\||$)', 1, 2, NULL, 1) second,
regexp_substr(str, '(.*?)(\||$)', 1, 3, NULL, 1) third,
regexp_substr(str, '(.*?)(\||$)', 1, 4, NULL, 1) fourth
from tbl;
请注意,此正则表达式处理 NULL 元素并且仍将返回正确的值。其他一些答案使用'[^|]+'
的形式来解析字符串,但是当存在 NULL 元素时会失败,应该避免。证明见这里:https://***.com/a/31464699/2543416
【讨论】:
非常接近!但输出更改在此处输入图像描述对于第一个查询,我应该得到 NULL。对于第二个查询,我应该得到 DY&009,对于第三个查询,我应该在某个地方得到地址。 您的输出会发生变化,因为管道位于不同的位置,因此字段的顺序不同。首先,您需要以一致的布局获取数据。你的每一个例子都是不同的。请运行上面的最后一个示例,粘贴不同的示例,您将看到。在解决解析问题之前解决您的数据一致性问题。 @Monali。检查我的答案的最后编辑。它应该可以工作。如果您有任何不工作的情况,请告诉我。【参考方案2】:没有足够的声誉来评论 Chris Johnson 的答案,所以添加我自己的。 Chris 有使用反向引用的正确方法,但忘记转义 Pipe 字符。 正则表达式将如下所示。
WITH dat
AS (SELECT 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details' AS str,
3 AS pos
FROM DUAL
UNION
SELECT ' |Jack|Sparrow|17-09-16||Address at some where|details' AS str,
4 AS pos
FROM DUAL)
SELECT str,
pos,
REGEXP_REPLACE (str, '^([^\|]*\|)' || pos || '([^\|]*)\|.*$', '\2')
AS regex_result
FROM dat;
我通过动态添加管道字符的位置来动态创建正则表达式。
结果如下所示。
|Jack|Sparrow|17-09-16||地址在一些地方|详情(4):
Jack|Sparrow|17-09-16|DY7009|地址在一些地方|详情(3):DY7009
【讨论】:
谢谢,感谢您的回答。我想,我没有问对。我只想要一个正则表达式在第 n 次出现管道符号后获取“字符串/字符串”。我不想替换任何字符串,所以只有 regexp_substr 可以完成这项工作。【参考方案3】:您可以使用 regex_replace 来获取第 n 个匹配组。在您的示例中,可以像这样检索第四个匹配项:
select regexp_replace(
'Jack|Sparrow|17-09-16|DY7009|Address at some where|details',
'^([^\|]*\|)3([^\|]*)\|.*$',
'\4'
) as col
from dual;
编辑:感谢 Arijit Kanrar 指出缺少的转义字符。
致 OP:regex_replace 不会替换数据库中的任何内容,只会替换返回的字符串。
【讨论】:
您是否检查过此查询是否有效?我不这么认为。【参考方案4】:您可以使用此查询来获取特定列(第 n 次出现)的值,如下所示
SELECT nth_string
FROM
(SELECT TRIM (REGEXP_SUBSTR (long_string, '[^|]+', 1, ROWNUM) ) nth_string ,
level AS lvl
FROM
(SELECT REPLACE('Jack|Sparrow|17-09-16|DY7009|Address at some where|details','||','| |') long_string
FROM DUAL
)
CONNECT BY LEVEL <= REGEXP_COUNT ( long_string, '[^|]+')
)
WHERE lvl = 4;
请注意,我在 oracle 中使用标准查询将分隔字符串拆分为记录。为了像第二种情况一样处理分隔符之间的空白,我将其替换为空格 ' '
。应用 TRIM() 函数后,空间被转换为 NULL。
您可以通过在查询末尾替换lvl =
中的数字来获取任何nth
记录。
让我知道您的反馈。谢谢。
编辑:
它似乎不适用于纯粹的 regexp_substr()
,因为没有办法在 '||' 之间转换空白到 Oracle NULL
。所以中间的 TRIM()
是必需的,我添加了一个 replace
以使其更容易。会有模式直接匹配这个场景,但是找不到。
这是第四次发生的所有场景。
WITH t
AS (SELECT '|Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT 'Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT '||Jack|Sparrow|SQY778|17JULY17|00J1' long_string
FROM dual)
SELECT long_string,
Trim (Regexp_substr (mod_string, '\|([^|]+)', 1, 4, NULL, 1)) nth_string
FROM (SELECT long_string,
Replace(long_string, '||', '| |') mod_string
FROM t) ;
LONG_STRING NTH_STRING
------------------------ -----------
|Jack|Sparrow|SQY778|17JULY17||00J1 17JULY17
Jack|Sparrow|SQY778|17JULY17||00J1 NULL
||Jack|Sparrow|SQY778|17JULY17|00J1 SQY778
EDIT2:终于找到了一个提供解决方案的模式。感谢 Gary_W
要从字符串中获取nth
,请使用:
WITH t
AS (SELECT '|Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT 'Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT '||Jack|Sparrow|SQY778|17JULY17|00J1' long_string
FROM dual)
SELECT long_string,
Trim (regexp_substr (long_string, '(.*?)(\||$)', 1, :n + 1, NULL, 1)) nth_string
FROM t;
【讨论】:
谢谢!请照顾新的更新编辑---有问题我已经更新了它。'[^|]+'
不适用于您发现的 NULL 元素。使用:select regexp_substr(long_string, '(.*?)(\||$)', 1, 4, NULL, 1)
。请注意,以管道开头的字符串在管道前面确实有一个 NULL 元素。糟糕的数据确实是这里的问题。
如果我们在第 n 次出现时添加 :n + 1 就可以了。 。IE。第 4 次出现,应该是 5 次。无论如何,谢谢!以上是关于如何在第 n 次出现管道“|”后获取字符或字符串ORACLE 中使用 REGULAR_EXPRESSION 的符号?的主要内容,如果未能解决你的问题,请参考以下文章
PLSQL 在第 N 次和第 M 次出现字符之间选择 substr
如何在第 n 次出现配置单元之前进行 regexp_extract
如何使用 2 个不同的模式获取第 n 次出现之间的所有字符串