如何在第 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 次出现之间的所有字符串

如何在 Hive 中构建正则表达式以获取字符串,直到第 N 次出现分隔符

在第n次出现空格后删除所有文本