1

如何匹配所有以 开头loockup.和结尾_id但没有前缀的字符串msg?下面是一些例子:

lookup.asset_id -> should match
lookup.msg_id -> shouldn't match
lookup.whateverelse_id -> should match

我知道甲骨文不支持消极的后视(即(?<!))......所以我试图明确列举使用交替的可能性:

regexp_count('i_asset := lookup.asset_id;', 'lookup\.[^\(]+([^m]|m[^s]|ms[^g])_id') <> 0 then
    dbms_output.put_line('match'); -- this matches as expected
end if;

regexp_count('i_msg := lookup.msg_id;', 'lookup\.[^\(]+([^m]|m[^s]|ms[^g])_id') <> 0 then
    dbms_output.put_line('match'); -- this shouldn’t match
                                   -- but it does like the previous example... why?
end if;

第二个regexp_count表达式不应该匹配......但它确实喜欢第一个。我错过了什么吗?

编辑

在实际用例中,我有一个字符串,其中包含可能包含多个lookup.xxx_id实例的 PL/SQL 代码:

declare
    l_source_code varchar2(2048) := '
        ...
        curry := lookup.curry_id(key_val => ''CHF'', key_type => ''asset_iso'');
        asset : = lookup.asset_id(key_val => ''UBSN''); -- this is wrong since it does
                                                        -- not specify key_type
        ...
        msg := lookup.msg_id(key_val => ''hello''); -- this is fine since msg_id does
                                                    -- not require key_type
    ';
    ...
 end;

我需要确定是否至少有一个错误lookup,即所有出现的地方,除了lookup.msg_id,还必须指定key_type参数。

4

2 回答 2

1

使用lookup\.[^\(]+([^m]|m[^s]|ms[^g])_id,您基本上是在要求检查字符串

  1. lookup.表示开始lookup\.
  2. 后跟至少一个不同于由(表示的字符[^\(]+
  3. 其次是——( | | )
    • m与--不同的一个字符[^m],或
    • 两个字符:m加上没有s-- m[^s],或
    • 三个字符:ms并且没有g--ms[^g]
  4. 结尾用_id表示_id

因此,对于lookup.msg_id,第一部分显然匹配,第二部分消耗ms,并为第三部分的第一个选择留下g

这可以通过将第三部分修补为始终为三个字符长(如lookup\.[^\(]+([^m]..|m[^s.]|ms[^g])_id. 然而,这会使一切都失败,其中 和 之间的部分lookup.长度_id至少为四个字符:

WITH
Input (s, r) AS (
  SELECT 'lookup.asset_id', 'should match' FROM DUAL UNION ALL
  SELECT 'lookup.msg_id', 'shouldn''t match' FROM DUAL UNION ALL
  SELECT 'lookup.whateverelse_id', 'should match' FROM DUAL UNION ALL
  SELECT 'lookup.a_id', 'should match' FROM DUAL UNION ALL
  SELECT 'lookup.ab_id', 'should match' FROM DUAL UNION ALL
  SELECT 'lookup.abc_id', 'should match' FROM DUAL
)
SELECT
  r, s, INSTR(s, 'lookup.msg_id') has_msg, REGEXP_COUNT(s , 'lookup\.[^\(]+([^m]..|m[^s]|ms[^g])_id') matched FROM Input
;

|               R |                      S | HAS_MSG | MATCHED |
|-----------------|------------------------|---------|---------|
|    should match |        lookup.asset_id |       0 |       1 |
| shouldn't match |          lookup.msg_id |       1 |       0 |
|    should match | lookup.whateverelse_id |       0 |       1 |
|    should match |            lookup.a_id |       0 |       0 |
|    should match |           lookup.ab_id |       0 |       0 |
|    should match |          lookup.abc_id |       0 |       0 |

如果你只是要确定,有msg问题的位置没有,你可能想去 (INSTR(s, 'lookup.msg_id') = 0) AND REGEXP_COUNT(s, 'lookup\.[^\(]+_id') <> 0

为了代码清晰REGEXP_INSTR(s, 'lookup\.[^\(]+_id') > 0可能更可取……</p>

@j3d 如果需要更多详细信息,请发表评论。

于 2014-11-13T11:46:42.327 回答
0

由于要求仍然有点模糊......</p>

  1. 在分号处拆分字符串。
  2. 检查每个子字符串s是否符合:

    WITH Input (s) AS (
      SELECT '   curry := lookup.curry_id(key_val => ''CHF'', key_type => ''asset_iso'');' FROM DUAL UNION ALL
      SELECT 'curry := lookup.curry_id(key_val => ''CHF'', key_type => ''asset_iso'');' FROM DUAL UNION ALL
      SELECT 'asset := lookup.asset_id(key_val => ''UBSN'');' FROM DUAL UNION ALL
      SELECT 'msg := lookup.msg_id(key_val => ''hello'');' FROM DUAL
    )
    SELECT
      s
    FROM Input
    WHERE REGEXP_LIKE(s, '^\s*[a-z]+\s+:=\s+lookup\.msg_id\(key_val => ''[a-zA-Z0-9]+''\);$')
     OR
     ((REGEXP_INSTR(s, '^\s*[a-z]+\s+:=\s+lookup\.msg_id') = 0)
      AND (REGEXP_INSTR(s, '[(,]\s*key_type') > 0)
      AND (REGEXP_INSTR(s,
        '^\s*[a-z]+\s+:=\s+lookup\.[a-z]+_id\(( ?key_[a-z]+ => ''[a-zA-Z_]+?'',?)+\);$') > 0)) 
    ;
    
    
    |                                                                        S |
    |--------------------------------------------------------------------------|
    |[tab] curry := lookup.curry_id(key_val => 'CHF', key_type => 'asset_iso');|
    |      curry := lookup.curry_id(key_val => 'CHF', key_type => 'asset_iso');|
    |                                 msg := lookup.msg_id(key_val => 'hello');|
    

这将容忍右括号之前的多余逗号。但是如果输入在语法上是正确的,那么这样的逗号就不会存在。

于 2014-11-14T01:11:25.630 回答