javascript - 正则表达式排除模式
问题描述
我想从 PLSQL 脚本中提取“创建语句”。我知道这可以使用 Lexer/Parser 来完成,但我正在尝试使用 JavaScript Regex 来做到这一点。
给定包含此内容的“脚本”,我想提取不同的语句。
CREATE OR REPLACE TYPE BODY Cheopsregbp.SITE_OT AS
CONSTRUCTOR FUNCTION SITE_OT (
p_site_list_id VARCHAR2
, p_traductions TRADUCTIONS_MAP_ENTRY_CT := new TRADUCTIONS_MAP_ENTRY_CT()
)
RETURN SELF AS RESULT
AS
BEGIN
SELF.site_list_id := p_site_list_id;
SELF.traductions := p_traductions;
RETURN;
END;
STATIC FUNCTION convert_to_date(p_date_string in VARCHAR2, p_field_name_in in VARCHAR2, p_field_name_out IN OUT NOCOPY VARCHAR2) RETURN DATE IS
BEGIN
-- function to convert string to date and keep track of which field we are converting => needed to produce error
p_field_name_out := p_field_name_in; -- this will cause fieldName (declared in verify) to be updated before potential fail in next line
RETURN cast(to_timestamp(p_date_string, Cheopsregbp.API_CONST_HLPR.DATE_FORMAT) as date);
END convert_to_date;
STATIC FUNCTION convert_to_number(p_number_string in VARCHAR2, p_field_name_in in VARCHAR2, p_field_name_out IN OUT NOCOPY VARCHAR2) RETURN NUMBER IS
BEGIN
-- function to convert string to number and keep track of which field we are converting => needed to produce error
p_field_name_out := p_field_name_in; -- this will cause fieldName (declared in verify) to be updated before potential fail in next line
RETURN cast(p_number_string as number);
END convert_to_number;
STATIC FUNCTION from_json(p_json_object in BLOB) RETURN SITE_OT IS -- $$ref-ot-fromJson-BLOB
l_clob CLOB;
l_warning INTEGER;
l_offset INTEGER := 1;
l_csId INTEGER := nls_charset_id('UTF8');
l_lang_context INTEGER := DBMS_LOB.default_lang_ctx;
l_amount INTEGER := DBMS_LOB.lobMaxSize;
BEGIN
IF p_json_object IS NULL THEN
RETURN null;
END IF;
dbms_lob.createTemporary(lob_loc => l_clob, cache => false);
dbms_lob.convertToClob( dest_lob => l_clob
,src_blob => p_json_object
,amount => l_amount
,dest_offset => l_offset
,src_offset => l_offset
,blob_csId => l_csId
,lang_context => l_lang_context
,warning => l_warning);
apex_json.parse(l_clob);
RETURN from_json(''); -- '' => root-path -- works with apex_json.g_values!
END from_json;
STATIC FUNCTION from_json(p_parent in VARCHAR2) -- works with apex_json.g_values!
RETURN SITE_OT IS -- $$ref-ot-fromJson-CLOB
l_arr_count INTEGER;
l_parent VARCHAR2(2048 CHAR) := p_parent;
l_api_error API_ERROR_OT;
l_field_name Cheopsregbp.API_CONST_HLPR.CHAR256;
l_traductions TRADUCTIONS_MAP_ENTRY_CT := new TRADUCTIONS_MAP_ENTRY_CT();
l_result SITE_OT;
BEGIN
IF p_parent IS NOT NULL THEN l_parent := p_parent || '.'; END IF;
-- prepare list of traductions
l_arr_count := apex_json.get_count(p_path => l_parent || 'traductions'); -- works with apex_json.g_values!
IF l_arr_count > 0 THEN
FOR i in 1 .. l_arr_count LOOP
l_traductions.extend;
l_traductions(l_traductions.last) := TRADUCTIONS_MAP_ENTRY_OT.from_json( l_parent || 'traductions['||i||']'); -- $$ref-fromJSONListItemFn
END LOOP;
END IF;
l_result := SITE_OT( -- $$ref-fromJSONReturn
p_site_list_id => apex_json.GET_VARCHAR2( l_parent || 'site_list_id'), -- $$ref-returnJSONField
p_traductions => l_traductions
);
RETURN l_result;
EXCEPTION -- $$ref-fromJSONExceptions
WHEN NO_DATA_FOUND THEN
l_api_error := new API_ERROR_OT(Cheopsregbp.API_CONST_HLPR.NO_DATA_FOUND, Cheopsregbp.API_CONST_HLPR.HTTP_404, l_field_name);
l_api_error.sqlcode := sqlcode;
l_api_error.sqlerrm := sqlerrm;
l_api_error.stacktrace := 'SITE_OT.verify';
API_CORE_HLPR.add_error(l_api_error);
RETURN NULL;
WHEN OTHERS THEN
l_api_error := new API_ERROR_OT(Cheopsregbp.API_CONST_HLPR.INVALID_DATA, Cheopsregbp.API_CONST_HLPR.HTTP_400, l_field_name);
l_api_error.sqlcode := sqlcode;
l_api_error.sqlerrm := sqlerrm;
l_api_error.stacktrace := 'SITE_OT.verify';
API_CORE_HLPR.add_error(l_api_error);
RETURN NULL;
END from_json;
MEMBER PROCEDURE verify(p_parent IN VARCHAR2 := null) AS -- $$ref-ot-verify
l_params Cheopsregbp.API_CONST_HLPR.CHAR1024;
l_parent Cheopsregbp.API_CONST_HLPR.CHAR256;
l_api_error API_ERROR_OT;
BEGIN
IF p_parent IS NOT NULL THEN
l_parent := p_parent || '.';
END IF;
-- key field does not have to be present. POST => new => no PK yet; PUT => PK is in URL!
-- If PK value is specified in body then it should be checked against URL param value though (in business logic)!
/** traductions is REQUIRED!! */
IF SELF.traductions IS NULL THEN
l_api_error := new API_ERROR_OT('REQUIRED', 400, l_parent||'traductions');
l_api_error.sqlerrm := 'REQUIRED' || ':'|| l_parent||'traductions';
l_api_error.stacktrace := 'SITE_OT.verify';
API_CORE_HLPR.add_error(l_api_error);
END IF;
-- validate children (if any)
/** verify all traductions */
IF SELF.traductions IS NOT NULL AND SELF.traductions.COUNT > 0 THEN
<<verify_fields_loop>>
FOR i IN 1 .. SELF.traductions.COUNT LOOP
SELF.traductions(i).verify('traductions['||(i-1)||']'); -- $$verifyChild (UI zero-based)
END LOOP verify_fields_loop;
END IF;
END verify;
MEMBER PROCEDURE add_traductions(p_traductions_map_entry IN TRADUCTIONS_MAP_ENTRY_OT) IS -- $$OOT.ADD2
BEGIN
SELF.traductions.extend;
SELF.traductions(SELF.traductions.last) := p_traductions_map_entry;
END add_traductions;
END;
/
GRANT EXECUTE ON SITE_OT TO Cheopsregbp;
/
我必须得到 2 个陈述:
- 创建或替换类型主体...
- 在 SITE_OT 上授予执行权限以...
我正在考虑多次扫描文本以查找不同的已知语句。第二个很容易,但第一个很难。第一个命令几乎是整个文本。它在第二个文本上方结束。
我不能以 'CREATE OR REPLACE...' 开头并以 'END;' 结尾,因为 END; 也可以是另一个语句的一部分。
所以实际上我需要找到文本 CREATE OR REPLACE...END; 但跳过任何中间
'开始...结束;'
'如果...结束如果;'
'循环...结束循环;'
为了使它更难,这三个语句中的任何一个都可以在';'之前有一个“标签” 所以'LOOP... END LOOP some_label; 也应该跳过。
我能够找到所有 BEGIN...END 块,而无需在中间 END IF 或 END LOOP 部分使用正则表达式停止,BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;
但我似乎无法正确地完成 CREATE...END; 陈述。
我想出了正则表达式CREATE(BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;|.*?)END
,但在第一个开始块的 END 处再次停止。
解决方案
我只针对 Java 正则表达式而不是 javascript 测试了这个,所以 YMMV
尝试(CREATE(BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;|.*?)END?).*
IE 在 END 上放了一个“贪婪”的限定词;
推荐阅读
- objective-c - 在 Objective-c 中使用 Earlgrey 的 IOS Programmatic Tap
- firebase - 使用 Firebase 消息打开应用时 Flutter 显示通知
- javascript - Cookies 在 HTTP 页面之间工作,而不是在 HTTPS 页面之间工作
- c# - 无法在 Json 数组中获取 Object 的值
- r - 在尝试重新编码我的数据期间,我一直遇到错误:参数 2 必须命名,而不是未命名
- c# - 了解 LINQ 中的 DefaultIfEmpty
- javascript - 类型“{}”中缺少属性“submitAction”,但在类型中是必需的
- python - 使用索引列表从 GroupBy 中保留一些组
- java - Pitest:如何在不同的模块中设置正确的路径
- python - 带有 gcp python 的气流:ValueError:流必须在开头