0

Oracle での正規表現の置換について助けが必要です。単語またはフレーズが一連のタグ内に存在しない限り、文書内に存在する単語またはフレーズをすべて置き換えたいと考えています。タグは私 (ホット html または xml) によって定義され、私の現在の概念は次のとおりです。

<term type=pos id=123>some phrase</term>

次のような regexp_replace の関数ラッパー (機能しない) を作成しました。

  FUNCTION ANNOTATE_ONE_TERM(IN_TEXT IN VARCHAR2, SEARCH_TERM IN VARCHAR2, TERM_TYPE IN VARCHAR2, RECORD_ID IN NUMBER) RETURN CLOB
  IS
    REGEX_SEARCH VARCHAR2(512);
    REGEX_REPLACE VARCHAR2(512);
  BEGIN
    REGEX_SEARCH := '((<TERM.*?</TERM>|[^<])*?)(^|\W)('|| SEARCH_TERM ||')($|\W)';
    REGEX_REPLACE := '\1 <TERM ID='|| TO_CHAR(RECORD_ID)||' TYPE=' || TERM_TYPE ||'>'|| SEARCH_TERM ||'</TERM> ';
    DBMS_OUTPUT.PUT_LINE('REGEX_SEARCH = ' || REGEX_SEARCH);
    DBMS_OUTPUT.PUT_LINE('REGEX_REPLACE = ' || REGEX_REPLACE);
    RETURN TRIM(REGEXP_REPLACE(IN_TEXT, REGEX_SEARCH, REGEX_REPLACE,1,0,'in'));
  END ANNOTATE_ONE_TERM;

このように呼び出すと、

SELECT ANNOTATE_ONE_TERM(
                         ANNOTATE_ONE_TERM('dog elephant dog cat cat dog dogfish fishdog mouse dog', 'DOG CAT', 'POS', 123),
                         'DOG', 'POS',456) 
FROM DUAL;

戻ります。

<TERM ID=456 TYPE=POS>DOG</TERM> elephant <TERM ID=123 TYPE=POS>DOG CAT</TERM> cat <TERM ID=456 TYPE=POS>DOG</TERM> dogfish fishdog mouse <TERM ID=456 TYPE=POS>DOG</TERM>

どちらが正しい。しかし、これで呼び出された場合;

SELECT ANNOTATE_ONE_TERM(
                         ANNOTATE_ONE_TERM('elephant dog cat cat dogfish fishdog mouse', 'DOG CAT', 'POS', 123),
                         'DOG', 'POS',456) 
FROM DUAL;

戻ります。

elephant <TERM ID=123 TYPE=POS <TERM ID=456 TYPE=POS>DOG</TERM> CAT</TERM> cat dogfish fishdog mouse

これは間違っています。">" を食べて、タグ内の単語/フレーズを見つけているようです。

私は積極的に正規表現についての知識を増やそうとしていますが、これはこれまで私を逃してきました.

4

1 に答える 1

1

「否定的に」一致しようとしたことは理解しています。終了マークアップを使用して直接一致を試みましたが、<\TERM>うまくいくようです:

create or replace FUNCTION ANNOTATE_ONE_TERM(IN_TEXT      IN VARCHAR2,
                                             SEARCH_TERM  IN VARCHAR2,
                                             TERM_TYPE    IN VARCHAR2,
                                             RECORD_ID    IN NUMBER)
RETURN CLOB IS
    REGEX_SEARCH  VARCHAR2(512);
    REGEX_REPLACE VARCHAR2(512);
BEGIN
    REGEX_SEARCH := '(?</TERM>| |^)' || SEARCH_TERM || '( |$)';
    REGEX_REPLACE := '\1<TERM ID=' || TO_CHAR(RECORD_ID) || ' TYPE=' 
                     || TERM_TYPE || '>' || SEARCH_TERM || '</TERM>\2';

    RETURN TRIM(REGEXP_REPLACE(IN_TEXT, REGEX_SEARCH, REGEX_REPLACE,1,0,'in'));
END ANNOTATE_ONE_TERM;

次に、以下を取得します。

SELECT ANNOTATE_ONE_TERM(
           ANNOTATE_ONE_TERM('dog elephant dog cat cat dog dogfish fishdog mouse dog',
                             'DOG CAT', 'POS', 123),
           'DOG', 'POS',456) 
FROM DUAL;

与える:

<TERM ID=456 TYPE=POS>DOG</TERM> elephant <TERM ID=123 TYPE=POS>DOG CAT</TERM> cat <TERM ID=456 TYPE=POS>DOG</TERM> dogfish fishdog mouse <TERM ID=456 TYPE=POS>DOG</TERM>

SELECT ANNOTATE_ONE_TERM(
          ANNOTATE_ONE_TERM('elephant dog cat cat dogfish fishdog mouse',
                            'DOG CAT', 'POS', 123),
          'DOG', 'POS',456) 
FROM DUAL;

与えます:

elephant <TERM ID=123 TYPE=POS>DOG CAT</TERM> cat dogfish fishdog mouse

予想通り、交差項はありません。Oracleは先読み/後読みアサーションをサポートしていないため(少なくとも私のバージョン11gでは)、このようなトリックを使用する必要があります。

于 2013-09-04T15:23:31.310 に答える