如何在PL / sql中实现NegEx?

时间:2013-08-31 19:38:17

标签: regex oracle plsql

我在正则表达式方面的技巧充其量只是微不足道。但是我有一个任务,我需要阅读医疗类型的文本,并标记不同类型的单词。另外,我需要确定该术语是否被否定。似乎有一组用Python编写并移植到Java的例程,它们可以完成我需要的类型。它们被称为Context / Negex,可以在这里找到; Google Code Negex Project

我可以阅读Java,我理解他们正在尝试做的一些事情。我的理解是他们用术语扫描句子标记术语,然后循环一组“否定短语”并标记否定词,并将原始术语标记更改为否定。

我的第一个问题是,是否有人知道这种常规的Oracle端口? (一种选择是将Java版本实现为Oracle Java存储过程,但我会发现难以修改和支持)。 如果没有,我对正则表达式有疑问;

问题:在没有嵌套的情况下替换先前替换的子集。

说我有一个包含的字符串;

  狗大象狗猫猫狗老鼠

然后我要标记两个短语

1) dog cat 
2) dog

编辑:需要将狗作为一个独立的单词来处理,并且不会像下面的鲨鱼或鱼狗一样;

  狗大象狗猫猫狗鲨鱼鱼狗老鼠

我会用“狗猫”代替所有“狗猫”;

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

我现在需要更换所有术语“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

似乎吃了一个尾随的“&gt;”并嵌套标签。

感谢所有其他帮助。

2 个答案:

答案 0 :(得分: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>'
)

fiddle

答案 1 :(得分:0)

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

演示here