【问题标题】:Using REGEXP_SUBSTR to get key-value pair data使用 REGEXP_SUBSTR 获取键值对数据
【发布时间】:2015-03-03 23:41:19
【问题描述】:

我有一列具有以下值,

User_Id=446^User_Input=L307-60#/25" AP^^

我正在尝试根据指定的键获取每个单独的值。

  1. User_Id= 之后的所有值,直到遇到 ^
  2. User_Input= 之后的所有值,直到遇到 ^

我试过了,到目前为止我有这个,

SELECT  LTRIM(REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^'
          ,'[0-9]+',1,1),'^') User_Id 
from dual

如何获取 User_Input 的值?

P.S:用户输入可以包含任何内容,例如 ',"、*、%,包括字符串中间的 ^(即,不作为分隔符)。

任何帮助将不胜感激..

【问题讨论】:

  • 如果“用户输入可以有任何东西”你确定它不能有^吗?如果它可以有一个插入符号,你如何区分作为数据一部分的插入符号和充当分隔符的插入符号?是否有理由需要使用正则表达式而不是 INSTRSUBSTR
  • 你是对的,用户输入可以有^,应用程序没有停止阻止他们输入。我只是在尝试使用正则表达式的方法,如果您可以建议一种使用 INSTR 和 SUBSTR 的方法,那也很棒..
  • 这种字符串看起来像是 xml 文档元素中经过修改的一组属性。如果您正在解析 xml,那么使用 Oracle 的 XML 解析功能是有价值的。
  • 如果你有字符串 "User_Id=446^User_Input=L^307-^60^#/25" AP^" 你想返回什么?你想修改你发布的算法吗?当它找到第一个插入符号并读取到字符串末尾而忽略最后一个插入符号时它不会停止?如果我们实现您指定的算法,我们将只返回“L”。可能还有其他键/值对在User_Input之后?
  • 我不久前就这个主题写了一个答案 - 它获取给定字符串中的所有 name=value 对:stackoverflow.com/a/28597947

标签: string oracle oracle12c


【解决方案1】:

这可以使用无聊的旧INSTR 来计算 KEY 和 VALUE 字符串的起点和终点的偏移量来轻松解决。

诀窍是使用可选的出现参数来识别= 的每个正确实例。因为输入可以包含不打算用作分隔符的插入符号,我们需要使用负位置来标识最后一个 ^

with cte as  (
  select kv
         , instr(kv, '=', 1, 1)+1 as k_st  -- first occurrence 
         , instr(kv, '^', 1) as k_end
         , instr(kv, '=', 1, 2)+1 as v_st  -- second occurrence 
         , instr(kv, '^', -1) as v_end     -- counting from back
  from t23
  )
select substr(kv, k_st, k_end - k_st) as user_id
       , substr(kv, v_st, v_end - v_st) as user_input
from cte
/

这里是requisite SQL Fiddle to prove it works。我认为它比任何正则表达式都更容易理解。

【讨论】:

    【解决方案2】:

    如果没有特别需要使用正则表达式,类似这样的东西会返回值。

    WITH rslt AS (
    SELECT 'User_Id=446^User_Input=L307-60#/25" AP^' val 
      FROM dual
    )
    SELECT LTRIM(SUBSTR(val
                       ,INSTR(val, '=', 1, 2) + 1
                       ,INSTR(val, '^', 1, 2) - (INSTR(val, '=', 1, 2) + 1)))
      FROM rslt;
    

    当然,如果你不能保证不会有任何插入符号是有效的文本字符,这可能会返回部分结果。

    【讨论】:

    • 是的,这也会从字符串中过滤掉 ^。感谢您的尝试!
    【解决方案3】:

    假设您的字符串中始终包含“User_Id=”和“User_Input=”,我将使用字符组方法进行解析

    使用起始锚点^ 和结束锚点$。寻找'User_Id=''User_Input='

    将您要搜索的值与字符组相关联。

        SCOTT@dev> 
      1  SELECT REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^','^User_Id=(.*\^)User_Input=(.*\^)$',1, 1, NULL, 1) User_Id
      2* FROM dual
    SCOTT@dev> /
    
    USER
    ====
    446^
    
    
    SCOTT@dev> 
      1  SELECT REGEXP_SUBSTR('User_Id=446^User_Input=L307-60#/25" AP^','^User_Id=(.*\^)User_Input=(.*\^)$',1, 1, NULL, 2) User_Input
      2* FROM dual
    SCOTT@dev> /
    
    USER_INPUT
    ================
    L307-60#/25" AP^
    
    SCOTT@dev> 
    

    【讨论】:

      【解决方案4】:

      从我的一个朋友那里得到这个答案。看起来很简单,效果很好...

      SELECT
      regexp_replace('User_Id=446^User_Input=L307-60#/25" AP^^', '.*User_Id=([^\^]+).*', '\1') User_Id,
      regexp_replace('User_Id=446^User_Input=L307-60#/25" AP^^', '.*User_Input=(.*)[\^]$', '\1') User_Input
      FROM dual
      

      在这里发帖以防万一你们觉得有趣..

      【讨论】:

        猜你喜欢
        • 2018-07-05
        • 1970-01-01
        • 1970-01-01
        • 2020-10-10
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-15
        相关资源
        最近更新 更多