如何匹配以loockup.
开头并以_id
结尾但不以msg
为前缀的所有字符串?以下是一些例子:
lookup.asset_id -> should match
lookup.msg_id -> shouldn't match
lookup.whateverelse_id -> should match
我知道Oracle不支持负面的后观(即(?<!)
)...所以我试图使用交替显式枚举可能性:
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
参数。
答案 0 :(得分:1)
使用lookup\.[^\(]+([^m]|m[^s]|ms[^g])_id
,您基本上要求检查字符串
lookup.
表示的lookup\.
开头,(
表示的[^\(]+
不同的字符,( | | )
m
- [^m]
或m
加上没有s
- m[^s]
或ms
而没有g
- ms[^g]
和_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
可能更合适......
@ j3d如果需要进一步的细节,请发表评论。
答案 1 :(得分:0)
由于要求仍然含糊不清......
检查每个子字符串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');|
这将容忍在右括号之前的多余逗号。但是如果输入在语法上是正确的,那么这样的逗号将不存在。