Regex:如何在PL/SQL中实现负查找
如何匹配以Regex:如何在PL/SQL中实现负查找,regex,plsql,negative-lookbehind,Regex,Plsql,Negative Lookbehind,如何匹配以loockup.开头、以\u 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;
loockup.
开头、以\u 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;
我需要确定是否至少有一个错误的查找
,即除查找之外的所有事件。msg_id
,还必须指定键类型
参数。使用查找[^(]+([^m]]m[^s]]ms[^g])u id
,您基本上是要求检查字符串
以查找开始。
由查找\.
表示
后跟至少一个不同于(
的字符,由[^\(]+
表示)
后跟--(| |)
- 与
m
不同的一个字符--[^m]
,或
- 两个字符:
m
加上nos
--m[^s]
,或
- 三个字符:
ms
和nog
--ms[^g]
,以及
以\u id
结尾,由\u id
表示
因此,对于lookup.msg_id
,第一部分显然匹配,第二部分消耗ms
,并将g
留给第三部分的第一个备选方案
这可以通过将第三部分修补为始终三个字符的长度来解决,如查找\.[^(]+([^m]..m[^s.]|ms[^g])\u id
。但是,如果查找。
和\u 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)和REGEXP_计数(s'lookup\.[^\(]+_id')0
为了代码清晰起见,REGEXP_INSTR(s,'lookup\.[^\(]+\u id')>0
可能更可取
@如果需要进一步的细节,j3d只需发表评论。要求仍然有点模糊
在分号处拆分字符串
检查每个子串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');|
这将允许在右括号之前使用多余的逗号。但是如果输入语法正确,这样的逗号将不存在。是单个字符串还是多个字符串的串联?可以有很多级别,比如“lookup.tunnel.east.msg\u id”那么“lookup.tunnel.east.alternative\u msg\u id”呢需要nfo。不,只有一个级别。总是lookup.xyz_id(param1,param2,paramN)
。感谢您的精彩回复。如果在同一字符串中出现更多的查找.xxx\u id
,该怎么办?在现实世界中,我需要检查可能包含任何数量的匹配或不匹配查找实例的源代码。@j3d您能提供更多详细信息吗?特别是:还有更多的“黑名单”吗不仅仅是lookup.msg_id
?如果字符串同时包含待匹配和不待匹配的令牌,那么预期的响应是什么?检查的更大目的是什么?@j3d我说得对吗:(I)最初,您想挑出msg
令牌,以避免应用keytype
检查?(ii)您需要检查语义,但不检查语法符合性-换句话说:例如,将不会缺少引号,但key\u type
参数可能会丢失?(iii)对要遵守的值的任何其他限制(大小写、特殊字符(不允许)等)?只有在查找时,key\u type
参数可能会丢失。
后面跟着msg\u id
。对于任何其他情况,必须指定key\u type
参数(或者至少指定两个参数)。@j3d我想,更新中的资产:=
中的第二个空格有错误?
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');|