代码之家  ›  专栏  ›  技术社区  ›  Artemio Ramirez

POSIX ERE正则表达式查找重复子字符串

  •  2
  • Artemio Ramirez  · 技术社区  · 8 年前

    我有一组字符串,其中最小值为1,最大值为3,格式如下:

    123;456;789
    123;123;456
    123;123;123
    123;456;456
    123;456;123
    

    我试图写一个正则表达式,这样我可以在同一个字符串上找到重复的值,如果你有 123;456;789 它会回来的 null 但是如果你有 123;456;456 它会回来的 456 对于 123;456;123 123

    我设法写下了这个表达:

    (.*?);?([0-9]+);?(.*?)\2
    

    它在返回的意义上起作用 当没有重复的值,但它没有准确返回所需的值时,例如:对于字符串 123;456;456 123;456;456 123;123;123 它回来了 123;123

    我需要的是只返回 ([0-9]+) 根据我所读到的,表达式的一部分通常使用非捕获组来完成。但要么我做错了,要么Oracle SQL不支持这一点,就像我尝试使用 ?: 语法结果不是我所期望的。

    SELECT REGEXP_SUBSTR(column, "expression") FROM DUAL;
    

    编辑:

    实际上根据 https://docs.oracle.com/cd/B12037_01/appdev.101/b10795/adfns_re.htm

    根据 https://www.regular-expressions.info/refcapture.html

    POSIX ERE不支持非捕获组

    3 回复  |  直到 8 年前
        1
  •  1
  •   TheChetan    8 年前

    This answer 描述如何从正则表达式中选择匹配组。所以用这个,

    SELECT regexp_substr(column, '(\d{3}).*\1', 1, 1, NULL, 1) from dual;
    #                                                       ^ Select group 1
    

    Working demo 正则表达式(礼貌:OP)。

        2
  •  1
  •   Gordon Linoff    8 年前

    select (case when val1 in (val2, val3) then val1
                 when val2 = val3 then val2
            end) as repeated
    from (select t.*,
                 regexp_substr(col, '[^;]+', 1, 1) as val1,
                 regexp_substr(col, '[^;]+', 1, 2) as val2,
                 regexp_substr(col, '[^;]+', 1, 3) as val3
          from t
         ) t
    where val1 in (val2, val3) or val2 = val3;
    
        3
  •  0
  •   Gary_W    8 年前

    请容忍我,想想这种不同的方法。以不同的方式看待这个问题,并以一种更灵活的方式对其进行分解,使您能够查看数据。这可能适用于你的情况,也可能不适用于你的情况,但希望你能记住,解决问题的方法总是不同的。

    通过在行中的数据,您可以看到其他聚合函数如何应用于切片和骰子以揭示模式等。

    SQL> with tbl_orig(id, str) as (
         select 1, '123;456;789' from dual union all
         select 2, '123;123;456' from dual union all
         select 3, '123;123;123' from dual union all
         select 4, '123;456;456' from dual union all
         select 5, '123;456;123' from dual
       ),
       tbl_split(id, element) as (
       select id,
              regexp_substr(str, '(.*?)(;|$)', 1, level, NULL, 1) element
       from tbl_orig
       connect by level <= regexp_count(str, ';')+1
       and prior id = id
       and prior sys_guid() is not null
       )
       --select * from tbl_split;
       select distinct id, element, count(element)
       from tbl_split
       group by id, element
       --having count(element) > 1
       order by id;
    
            ID ELEMENT     COUNT(ELEMENT)
    ---------- ----------- --------------
             1 123                      1
             1 456                      1
             1 789                      1
             2 123                      2
             2 456                      1
             3 123                      3
             4 123                      1
             4 456                      2
             5 123                      2
             5 456                      1
    
    10 rows selected.
    
    SQL>
    
    推荐文章