【问题标题】:How to make regular expression correctly?如何正确地制作正则表达式?
【发布时间】:2011-12-02 19:29:40
【问题描述】:

我需要从“*”的第三次出现位置到第四次获取数据。我这样做:

    with t as (select 'T*76031*12558*test*received percents' as txt from dual)
         select regexp_replace(txt, '.*(.{4})[*][^*].*$', '\1')
    from t

我收到“测试” - 没错,但如何获得任意数量的字符,而不仅仅是 4 个?

【问题讨论】:

    标签: regex oracle plsql oracle10g


    【解决方案1】:

    根据您使用的示例,这应该可以工作:

    REGEXP_REPLACE( txt, '(^.*\*.*\*.*\*)([[:alnum:]]*)(\*.*$)', '\2')
    

    所以 SELECT 将是:

    WITH t 
      AS (SELECT 'T*76031*12558*test*received percents' AS txt FROM DUAL)
    SELECT REGEXP_REPLACE( txt, '(^.*\*.*\*.*\*)([[:alnum:]]*)(\*.*$)', '\2')
      FROM t;
    

    正则表达式查找:

    第 1 组: 字符串的开头。最多为 '' 的任意数量的字符。 m 到另一个 '' 的任何其他字符。直到第三个“*”的任何其他字符。

    第 2 组: 任何字母数字字符

    第 3 组: '*' 后跟任何其他字符,直到字符串的末尾。

    将上述所有内容替换为第 2 组中的所有内容。

    希望这会有所帮助。

    编辑: 继 Rob van Wijk 的另一个帖子的精彩回答之后:

    Exracting substring from given string

    WITH t 
      AS (SELECT 'T*76031*12558*test*received percents' AS txt FROM DUAL)
    SELECT REGEXP_SUBSTR( txt,'[^\*]+',1,4)
      FROM t;
    

    【讨论】:

    • 没问题,您可以将第 1 组模式稍微压缩为 REGEXP_REPLACE( txt, '^(.**){3}([[:alnum:]]*)(*.*$ )', '\2') 如果需要,但我认为指定它已满更明显。
    • 它不适用于以下字符串:“B*44511*_____Result in_”
    • 我已经修复了:“(^.**.**.**)([[:alnum:][:space:]]*)(*.*$)”
    • 我会指定 OR 运算符 Dmitry 所以它是 [[:alnum:]] 或 [[:space:]] 例如REGEXP_REPLACE(txt, '^(.**){3}(([[:alnum:]]|[[:space:]])*)(*.*$)', '\2')
    • Ollie,好的,但是字符串可以包含除“*”之外的任何字符
    【解决方案2】:

    注意: 10g REGEXP_SUBSTR 不支持返回子表达式,参见下面的 cmets。

    如果您真的只选择字符串的一部分,我建议您改用REGEXP_SUBSTR。我不知道它是否更有效,但它会更好地记录您的意图:

    SQL> select regexp_substr('T*76031*12558*test*received percents', 
                              '^([^*]*[*]){3}([^*]*)', 1, 1, '', 2) from dual;
    
    REGEXP_SUBST
    ------------
    test
    

    以上我使用了 Pieter-Bas 提供的正则表达式。

    另见http://www.regular-expressions.info/oracle.html

    【讨论】:

    • 运行你的 SQL 给我:ORA-00939: 函数参数太多
    • @Ollie:荷兰!剪切和粘贴上面的代码在我的 11.2.0.1.0 上完美运行,但是是的,作者用 oracle10g 标记了这个问题,并且看起来 10g REGEXP_SUBSTR 不支持匹配子表达式。
    【解决方案3】:

    下面的呢?

     ^([^*]*[*]){3}([^*]*)
    

    第一部分匹配 3 组 *,第二部分匹配直到下一个 * 或行尾的所有内容。

    【讨论】:

    • Pieter-Bas,直到下一个 * 怎么办?
    • 将 {3} 更改为 {4}。这个正则表达式的作用是从行的开头 (^) 匹配 3 ({3}) 组任意数量的非星号字符 ([^*]*),后跟单个 * ([])。然后在第二组中匹配以下非起始字符序列 [^]*.
    【解决方案4】:

    您假设文本的最后一个 * 也是第四个。如果这个假设是真的,那么这个:

    \b\w*\b(?=\*[^*]*$)
    

    会得到你想要的。但当然,这只匹配最后一个星之前 * 之间的最后一个单词。在这种情况下,它只匹配 test 或 *. 内的任何单词字符。

    【讨论】:

    • @DmitryB 不,它只返回测试,因为它只匹配测试。如果要使用 \1,可以将单词括在 () 中
    • @FailedDev:我可以让正则表达式在 Perl 中工作,但不能在 Oracle 11g 中工作。你能告诉我你正在运行的代码吗?我一定有错字。
    • 这里没有 Oracle 机器,但它适用于我能想到的几乎所有其他正则表达式风格:s
    猜你喜欢
    • 2018-03-21
    • 2011-10-30
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 2011-02-05
    • 2022-07-06
    相关资源
    最近更新 更多