如何在PL/SQL中实现NegEx?

3
我的正则表达式技能最多只算及格。然而,我有一个任务需要阅读医学类型的文本,并标记不同类型的单词。此外,我需要确定术语是否被否定。看起来有一组用Python编写并移植到Java的程序可以做我需要的事情。它们被称为Context/Negex,并且可以在这里找到:Google Code Negex Project 我有点能读懂Java,并且我理解他们试图做的一些事情。我的理解是他们扫描术语句子以标记术语,然后循环遍历一组“否定短语”以标记负面术语,并将原始术语标记更改为否定。
我的第一个问题是,是否有人知道这种程序的Oracle版本?(一种选择是将Java版本实现为Oracle Java存储过程,但我会发现修改和支持困难。)如果没有,我对正则表达式有一个问题;
问题:替换先前替换的子集而不嵌套。
假设我有一个包含以下内容的字符串;
狗 大象 狗 猫 猫 狗 鼠标
然后我想标记两个短语。
1) dog cat 
2) dog

编辑:需要将“dog”作为一个单独的词处理,不会像下面这样匹配“dogfish”或“fishdog”;

dog elephant dog cat cat dog dogfish fishdog mouse

我会用“dog cat”替换所有的“dog cat”,得到如下结果:

dog elephant <term id=123 type=pos>dog cat</term> cat dog mouse

我现在需要将所有术语“dog”替换为“dog”,但不包括已经在任何以“<”开头的标记中的术语,结果如下:

<term id=456 type=pos>dog</term> elephant <term id=123 type=pos>dog cat</term> cat <term id=456 type=pos>dog</term> mouse

正则表达式能够实现这个吗?如果可以,那么该怎样写正则表达式才会使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(UPPER('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

看起来它吃掉了一个尾部的">"并嵌套了一个标签。

欢迎提供更多帮助。

2个回答

1
regexp_replace(  
  'dog elephant <term id=123 type=pos>dog cat</term> cat dog mouse',
  '((<term.*?</term>|[^<])*?)dog', 
  '\1<term id=456 type=pos>dog</term>'
)

此句话的英文原文为:"Translate from English to Chinese. The content is related to programming, preserving HTML, without explanation. fiddle"。

那对我所要求的工作得很好。不幸的是,我的表述不够清晰。在搜索字符串中,“dog”这个词需要是一个独立的单词,而不是其他单词的一部分。因此,它不应该匹配“dogfish”。我尝试了 code'((<term.?</term>|[^<])?)(^|\W)dog(\z|\W)'code,它可以工作,但会吞掉dog前后的空格。 - Paul Stearns
我在上面的问题中添加了一点内容。如果您有时间,我会很感激您能看一下。 - Paul Stearns
\W替换为空格字符。 - Egor Skriptunoff

0
REGEXP_REPLACE (
      REGEXP_REPLACE (source_string,
                      '(^| +)(dog cat)($| +)',
                      ' <term id=123 type=pos>\2</term> '),
      '(^| +)(dog)($| +)',
      ' <term id=456 type=pos>\2</term> ')

演示这里


猫、狗、鱼 怎么样? - Egor Skriptunoff
这就是为什么我使用 \W 而不是空格。迄今为止我所做的是 codetrim(regexp_replace( 'dog elephant <term id=123 type=pos>dog cat</term> cat dog dogfish mouse fishdog dog', '((<term.*?</term>|[^<])*?)(^|\W)dog($|\W)', '\1 <term id=456 type=pos>dog</term> ' ))code - Paul Stearns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接