How do I match all the strings that begin with loockup.
and end with _id
but not prefixed by msg
? Here below are some examples:
lookup.asset_id -> should match
lookup.msg_id -> shouldn't match
lookup.whateverelse_id -> should match
I know Oracle does not support negative lookbehind (i.e. (?<!)
)... so I've tried to explicitly enumerate the possibilities using alternation:
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;
The second regexp_count
expression should't match... but it does like the first one. Am I missing something?
EDIT
In the real use case, I've a string that contains PL/SQL code that might contains more than one lookup.xxx_id
instances:
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;
I need to determine whether there is at least one wrong lookup
, i.e. all occurrences, except lookup.msg_id
, must also specify the key_type
parameter.
With
lookup\.[^\(]+([^m]|m[^s]|ms[^g])_id
, you are basically asking to check for a stringlookup.
denoted bylookup\.
,(
denoted by[^\(]+
,( | | )
m
--[^m]
, orm
plus nos
--m[^s]
, orms
and nog
--ms[^g]
, and_id
denoted by_id
.So, for
lookup.msg_id
, the first part matches obviously, the second consumesms
, and leaves theg
for the first alternative of the third.This could be fixed by patching up the third part to be always three characters long like
lookup\.[^\(]+([^m]..|m[^s.]|ms[^g])_id
. This, however, would fail everything, where the part betweenlookup.
and_id
is not at least four characters long:If you have just to make sure, there is no
msg
in the position in question, you might want to go for(INSTR(s, 'lookup.msg_id') = 0) AND REGEXP_COUNT(s, 'lookup\.[^\(]+_id') <> 0
For code clarity
REGEXP_INSTR(s, 'lookup\.[^\(]+_id') > 0
might be preferable…@j3d Just comment if further detail is required.