【问题标题】:Regular Expression for REGEXP_SUBSTR in OracleOracle 中 REGEXP_SUBSTR 的正则表达式
【发布时间】:2015-04-19 06:45:27
【问题描述】:

我要搜索以下文本:

#S7Z OK
#Wed Feb 18 07:16:26 GMT 2015
expiration=10.0
lastModified=1424192425832
length=466472
path=/name/_master_/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf 
userType=

每个 = 前面的单词是属性的名称。对于每个属性名称,我想获取属性值。这意味着我正在寻找与 regexp_substr 一起使用的正则表达式来获取每个已知属性的值。

类似这样的:

SELECT REGEXP_SUBSTR(
'#S7Z OK
#Wed Feb 18 07:16:26 GMT 2015
expiration=10.0
lastModified=1424192425832
length=466472
path=/name/_master_/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf 
userType=',
'path=.+')
FROM dual

返回: path=/name/master/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf

但我只想要这个值,即“/name/master/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf”。 它也应该适用于过期、lastModified 等,也就是说,我不仅要搜索 url,而且要搜索任何类型的值。

如何在一个正则表达式中实现这一点?

【问题讨论】:

    标签: sql regex oracle regexp-substr


    【解决方案1】:

    这是一次捕获所有name=value 对的方法。请注意,我在正则表达式中使用了显式量词 {1,10} 来防止灾难性的回溯。 (这个特定的正则表达式实际上可能不受此限制,在这种情况下,您可以将显式量词替换为 +。但最好不要冒险!)

    WITH s1 AS (
        SELECT '#S7Z OK
    #Wed Feb 18 07:16:26 GMT 2015
    expiration=10.0
    lastModified=1424192425832
    length=466472
    path=/name/_master_/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf 
    userType=' AS str
          FROM dual
    )
    SELECT SUBSTR(name_value, 1, INSTR(name_value, '=') - 1) AS myname
         , SUBSTR(name_value, INSTR(name_value, '=') + 1, LENGTH(name_value)) AS myvalue
      FROM (
        SELECT REGEXP_SUBSTR(REGEXP_SUBSTR(s1.str,'(\S+=\S*\s*){1,10}'), '\S+', 1, LEVEL) AS name_value
          FROM s1
       CONNECT BY REGEXP_SUBSTR(REGEXP_SUBSTR(s1.str,'(\S+=\S*\s*){1,10}'), '\S+', 1, LEVEL) IS NOT NULL
    );
    

    输出如下:

    MYNAME       | MYVALUE
    -------------------------------------------------------------------------
    expiration   | 10.0
    lastModified | 1424192425832
    length       | 466472
    path         | /name/_master_/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf
    userType     | (null)
    

    Please see SQL Fiddle here.

    请注意,我可以在外部查询中使用REGEXP_SUBSTR(name_value, '^[^=]+') 等,但我认为此查询中有足够的正则表达式(它有点贵,我相信SUBSTR() 加上INSTR() 更便宜!) .另外请注意,如果您使用的是 Oracle 11g 或更高版本,CONNECT BY 子句可以替换为以下内容:

    CONNECT BY LEVEL <= REGEXP_COUNT(REGEXP_SUBSTR(s1.str,'(\S+=\S*\s*){1,10}'), '\S+')
    

    See revised SQL Fiddle.

    【讨论】:

      【解决方案2】:
      SELECT REGEXP_SUBSTR(
      '#S7Z OK
      #Wed Feb 18 07:16:26 GMT 2015
      expiration=10.0
      lastModified=1424192425832
      length=466472
      path=/name/_master_/563/5638ad54-8079-4399-ba2b-3257b6e6c7fd.pdf 
      userType=',
      'path=(.+)', 1, 1, null, 1)
      FROM dual;
      

      【讨论】:

      • 不错 - 虽然请注意,根据我的发现,这仅适用于 Oracle 11g +。
      • 谢谢,效果很好,而且速度非常快!
      【解决方案3】:

      '。 +=' 作为第二个参数 '' 作为第三个参数

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-28
        • 1970-01-01
        • 2019-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多