Problem:
Ein Text soll in PL/SQL nach Auftreten von Ausdrücken durchsucht werden. Als Ergebnis sollen die Treffer als Collection zurückgeben werden.Lösung:
Der hier vorgestellte Lösungsansatz basiert auf der Verwendung von Regular Expressions. Wir nutzen eine Nested Table zum Sammeln der gefundenen Token und nutzen diesen Typ auch als Rückgabe unserer Splitfunktion.Mit der Standard-PL/SQL-Funktion regexp_substr lassen sich Bereiche aus einem String herauslesen:
REGEXP_SUBSTR( source_string, pattern [, position [, occurrence [, match_parameter ]]] ) | source_string: Zu untersuchender Text pattern: regular expression position: Position in source_string, ab der gesucht werden soll occurence: Nr. des Tokens, welches als Ergebnis zurückgeben werden soll match_parameter: kann eine beliebige Kombination der folgenden Angaben sein: i: Groß-/Kleinschreibung wird ignoriert c: Groß-/Kleinschreibung wird beachtet n: Punkt (.) im Pattern gibt an, dass neue Zeilen ebenfalls beachtet werden sollen m: ^ und $ markieren den Anfang bzw. das Ende einer Zeile bei Multi-Line Strings |
REGEXP_INSTR( source_string, pattern [, position [, occurrence [, return_option[, match_parameter ]]]] ) | source_string: Zu untersuchender Text pattern: regular expression position: Position in source_string, ab der gesucht werden soll occurence: Nr. des Tokens, welches als Ergebnis zurückgeben werden soll return_option: 0, wenn die erste Position eines gefundenen Tokens zurückgegeben werden soll; 1, wenn die Position nach dem gefundenen Token ausgegeben werden soll match_parameter: kann eine beliebige Kombination der folgenden Angaben sein: i: Groß-/Kleinschreibung wird ignoriert c: Groß-/Kleinschreibung wird beachtet n: Punkt (.) im Pattern gibt an, dass neue Zeilen ebenfalls beachtet werden sollen m: ^ und $ markieren den Anfang bzw. das Ende einer Zeile bei Multi-Line Strings |
Die zweite Lösung (reg_split_rec(p_string, p_pattern, p_pos)) verwendet einen rekursiven Ansatz, bei dem der nächste verfügbare Startpunkt an die nächste Rekursionsebene übergeben wird.
IMPLEMENTIERUNG ALS ANONYMER PL/SQL-BLOCK: ========================================== declare type nt_tab_vc2 is table of varchar2(4000); v_return nt_tab_vc2; function reg_split(p_string in varchar2, p_pattern in varchar2) return nt_tab_vc2 is v_ret nt_tab_vc2; begin v_ret := nt_tab_vc2(); select regexp_substr(p_string, p_pattern, 1, level) token bulk collect into v_ret from dual where regexp_substr(p_string, p_pattern, 1, level, 'i') is not null connect by regexp_instr(p_string, p_pattern, 1, level) > 0; return v_ret; end; function reg_split_rec(p_string in varchar2, p_pattern in varchar2, p_pos in number default 1) return nt_tab_vc2 is v_ret nt_tab_vc2; v_token varchar2(4000); v_pos_next number; begin v_token := regexp_substr(p_string, p_pattern, p_pos, 1); if v_token is not null then --pattern is found v_pos_next := regexp_instr(p_string, p_pattern, p_pos, 1, 1); v_ret := reg_split(p_string, p_pattern, v_pos_next); v_ret.extend(1); v_ret(v_ret.last) := v_token; return v_ret; else --pattern is not found return nt_tab_vc2(); end if; end; begin v_return := reg_split( 'Hello @world@! The weather is @great@ today.', '(\@)([a-z-]\w+)(\@)'); if v_return.count > 0 then for i in v_return.first .. v_return.last loop dbms_output.put_line(lpad(i, round(log(10,v_return.count))+1)||' '||v_return(i)); end loop; end if; end; BEISPIEL-AUSGABE: ================= 1 @world@ 2 @great@ |
Keine Kommentare:
Kommentar veröffentlichen