正则表达式排除模式

时间:2019-12-20 18:47:30

标签: javascript regex

我想从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条声明:

  1. 创建或替换类型的身体...
  2. GRAITE EXECUTE ON SITE_OT TO ...

我正在考虑多次扫描文本以查找不同的已知语句。 第二个很简单,但是第一个很困难。 第一个命令几乎是全文。它在第二个文本的上方结束。

我不能以'CREATE OR REPLACE ...'开头并以'END;'结尾,因为END;也可以是另一条语句的一部分。

所以实际上我需要找到文本CREATE OR REPLACE ... END;但跳过任何中级

'BEGIN ... END ;'
'IF ... END IF;'
“ LOOP ... END LOOP;”

更难的是,这三个语句中的任何一个都可以在';'之前加一个“标签” 因此,“ LOOP ... END ” LOOP some_label;也应该跳过。

我能够找到所有BEGIN ... END块,而不必使用正则表达式BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;停在中间END IF或END LOOP零件上,但是对于完整的CREATE ... END我似乎做不对。声明。

我想到了正则表达式CREATE(BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;|.*?)END,但是它在第一个begin块的END处再次停止。

1 个答案:

答案 0 :(得分:0)

我仅针对Java regex(而非javascript)进行了测试,因此YMMV

尝试(CREATE(BEGIN\s+.*?\s+END(?!\s+IF|\s+LOOP).*?;|.*?)END?).*

I.E。在END上放一个“贪婪”的限定词;