【问题标题】:regexp_substr skips over empty positionsregexp_substr 跳过空位
【发布时间】:2013-09-25 23:50:47
【问题描述】:

使用此代码返回管道分隔字符串中的第 n 个值...

regexp_substr(int_record.interfaceline, '[^|]+', 1, i)

当所有值都存在时它工作正常

Mike|Male|Yes|20000|Yes 所以3rd 的值为Yes(正确)

但如果字符串是

Mike|Male||20000|Yes,第三个值是20000(不是我想要的)

如何告诉表达式不要跳过空值?

TIA

迈克

【问题讨论】:

    标签: regex oracle plsql


    【解决方案1】:

    我在使用 CSV 文件时遇到了类似的问题,因此我的分隔符是分号 (;)
    所以我从如下表达式开始:

     select regexp_substr(';2;;4;', '[^;]+', 1, i) from dual 
    

    i 从 1 迭代到 5。

    当然也没有用。

    为了获得空白部分,我只是说它们可能位于开头 (^;)、中间 (;;) 或末尾 (;$)。并且将所有这些加在一起给出:

    select regexp_substr(';2;;4;', '[^;]+|^;|;;|;$', 1, i) from dual
    

    信不信由你:从 1 到 5 测试 i 有效!

    但我们不要忘记最后的细节:通过这种方法,你会得到 ;对于最初为空的字段。 接下来的几行展示了如何摆脱它们,用空字符串(nulls)轻松替换它们:

    stage1 为 (

    从对偶中选择 regexp_substr(';2;;4;', '[^;]+|^;|;;|;$', 1, 2) 作为 F

    )

    当 F like '%;' 时选择大小写then '' else F 从 stage1 结束

    【讨论】:

      【解决方案2】:

      作为@tbone 响应的补充...

      奇怪的是,我的 oracle 无法识别此列表中的空格字符:[^|] 在这种情况下,可能会令人困惑并且很难意识到出了什么问题。 试试这个正则表达式([^|]| )+。此外,要检测可能的第一个空白项,最好将分隔符替换为之前的空格,而不是之后: ' |'

      trim(regexp_substr(replace('A|test||string', '|', ' |'), '([^|]| )+', 1, 4))
      

      【讨论】:

        【解决方案3】:

        您可以使用以下内容:

        with l as (select 'Mike|Male||20000|Yes' str from dual)
        select regexp_substr(str,'(".*"|[^|]*)(\||$)',1,level,null,1) 
        from dual,l 
        where level=3/*use any position*/ connect by level <= regexp_count(str,'([^|]*)(\||$)')
        

        【讨论】:

          【解决方案4】:

          好的。这应该是最适合您的解决方案。

          SELECT
                REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                              '^([^|]*\|){2}([^|]*).*$',
                              '\2' )
                    TEXT
          FROM
                DUAL;
          

          所以对于你的问题

          SELECT
                REGEXP_REPLACE ( INCOMINGSTREAMOFSTRINGS,
                              '^([^|]*\|){N-1}([^|]*).*$',
                              '\2' )
                    TEXT
          FROM
                DUAL;
          

          --INCOMINGSTREAMOFSTRINGS 是带分隔符的完整字符串

          --你应该通过n-1来获得第n个位置

          备选方案 2:

          WITH T AS (SELECT 'Mike|Male||20000|Yes' X FROM DUAL)
          SELECT
                X,
                REGEXP_REPLACE ( X,
                              '^([^|]*).*$',
                              '\1' )
                    Y1,
                REGEXP_REPLACE ( X,
                              '^[^|]*\|([^|]*).*$',
                              '\1' )
                    Y2,
                REGEXP_REPLACE ( X,
                              '^([^|]*\|){2}([^|]*).*$',
                              '\2' )
                    Y3,
                REGEXP_REPLACE ( X,
                              '^([^|]*\|){3}([^|]*).*$',
                              '\2' )
                    Y4,
                REGEXP_REPLACE ( X,
                              '^([^|]*\|){4}([^|]*).*$',
                              '\2' )
                    Y5
          FROM
                T;
          

          备选方案 3:

          SELECT
                REGEXP_SUBSTR ( REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                                          '\|',
                                          ';' ),
                             '(^|;)([^;]*)',
                             1,
                             1,
                             NULL,
                             2 )
                    AS FIRST,
                REGEXP_SUBSTR ( REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                                          '\|',
                                          ';' ),
                             '(^|;)([^;]*)',
                             1,
                             2,
                             NULL,
                             2 )
                    AS SECOND,
                REGEXP_SUBSTR ( REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                                          '\|',
                                          ';' ),
                             '(^|;)([^;]*)',
                             1,
                             3,
                             NULL,
                             2 )
                    AS THIRD,
                REGEXP_SUBSTR ( REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                                          '\|',
                                          ';' ),
                             '(^|;)([^;]*)',
                             1,
                             4,
                             NULL,
                             2 )
                    AS FOURTH,
                REGEXP_SUBSTR ( REGEXP_REPLACE ( 'Mike|Male||20000|Yes',
                                          '\|',
                                          ';' ),
                             '(^|;)([^;]*)',
                             1,
                             5,
                             NULL,
                             2 )
                    AS FIFTH
          FROM
                DUAL;
          

          【讨论】:

          • 请编辑现有答案,不要创建多个答案。
          • @realspirituals - 这是一种享受。非常感谢您的时间(也感谢其他所有人抽出时间)。非常感谢
          【解决方案5】:

          regexp_substr 是这样工作的:

          如果出现次数大于 1,则 数据库搜索 第二次出现从后面的第一个字符开始 第一次出现模式,依此类推。这种行为不同 从 SUBSTR 函数开始搜索第二个 出现在第一次出现的第二个字符处。

          所以模式 [^|] 将寻找非管道字符,这意味着它将跳过连续管道(“||”)寻找非管道字符。

          你可以试试:

          select trim(regexp_substr(replace('A|test||string', '|', '| '), '[^|]+', 1, 4)) from dual;
          

          这将替换“|”带有“|”并允许您根据模式 [^|]

          进行匹配

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-26
            • 1970-01-01
            • 1970-01-01
            • 2012-06-15
            • 2015-01-28
            • 1970-01-01
            相关资源
            最近更新 更多