如何找到字符串的完全匹配并在Oracle中进行替换?

时间:2019-09-11 07:43:20

标签: regex oracle replace pattern-matching regexp-replace

如果单词在“单词”列中以超链接及其单词和ID退出,我将尝试替换句子中的单词。该表包含列ID单词和句子。下面的代码是我从一位乐于助人的同伴那里得到的。谢谢。

https://dbfiddle.uk/?rdbms=oracle_18&fiddle=8fe103264dc650ad4bd87b20f9c6931a

Create table temp(
  id       NUMBER,
  word     VARCHAR2(1000),
  Sentence VARCHAR2(2000)
);

insert into temp
SELECT 1,'automation testing', 'automtestingation testing is popular kind of testing' FROM DUAL UNION ALL
SELECT 2,'testing','manual testing' FROM DUAL UNION ALL
SELECT 3,'manual testing','this is an old method of testing' FROM DUAL UNION ALL
SELECT 5,'B-number analysis','B-number analysis table' FROM DUAL UNION ALL
SELECT 6,'B-number analysis table','testing B-number analysis' FROM DUAL;

MERGE INTO temp dst
USING (
  WITH ordered_words ( rn, id, word ) AS (
    SELECT ROW_NUMBER() OVER ( ORDER BY LENGTH( word ) ASC, word DESC ),
           id,
           word
    FROM   temp
  ),
  sentences ( rid, sentence, rn ) AS (
    SELECT ROWID,
           sentence,
           COUNT(*) OVER () + 1
    FROM temp
  UNION ALL
    SELECT s.rid,
           REGEXP_REPLACE(
             REGEXP_REPLACE(
               s.sentence,
               '(^|[^a-z])' || w.word || '($|[^a-z])',
               '\1' || 'http://localhost/'|| w.id ||'/<u>'||w.word ||'<u>' || '\2',
               1,
               0,
               'i'
              ),
             '(^|[^a-z])' || w.word || '($|[^a-z])',
             '\1' || w.word || '\2',
               1,
               0,
               'i'
              ),
           s.rn - 1
    FROM   sentences s
           INNER JOIN ordered_words w
           ON ( s.rn - 1 = w.rn ) 
  )
  SELECT rid, sentence
  FROM   sentences
  WHERE  rn = 1
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
  UPDATE
  SET    sentence = src.sentence;

要替换的值是https://localhost/“ id” /“ word”如果看到id = 5的值(B数分析),则句子是https://localhost/6/ localhost / 5 / B-数字分析表,但实际值应该是https://localhost/6/ B数字分析表。

当前输出:

ID   WORD                SENTENCE
1   automation testing  automtestingation http://localhost/2/<u>testing<u> 
                        is popular kind of http://localhost/2/<u>testing<u>
2   testing             http://localhost/3/<u>manual 
                        http://localhost/2/<u>testing<u><u>
3   manual testing      this is an old method of 
                        http://localhost/2/<u>testing<u>
5   B-number analysis   http://localhost/6/<u>http://localhost/5/<u>B- 
                        number analysis<u> table<u>
6   B-number analysis table http://localhost/2/<u>testing<u> 
                        http://localhost/5/<u>B-number analysis<u>

1 个答案:

答案 0 :(得分:2)

分两步进行:

  1. 首先在一些不会在您的文本中出现的包装器中,用ID替换字符串(即testing映射到${2}
  2. 然后,完成所有替换操作后,将包装的ID替换为网址(即${2}映射到http://localhost/2/<u>testing</u>

Oracle设置

Create table temp(
  id       NUMBER,
  word     VARCHAR2(1000),
  Sentence VARCHAR2(2000)
);

insert into temp
SELECT 1,'automation testing', 'automtestingation testing is popular kind of testing' FROM DUAL UNION ALL
SELECT 2,'testing','manual testing' FROM DUAL UNION ALL
SELECT 3,'manual testing','this is an old method of testing' FROM DUAL UNION ALL
SELECT 4,'punctuation','automation testing,manual testing,punctuation,automanual testing-testing' FROM DUAL UNION ALL
SELECT 5,'B-number analysis','B-number analysis table' FROM DUAL UNION ALL
SELECT 6,'B-number analysis table','testing B-number analysis' FROM DUAL UNION ALL
SELECT 7,'Not Matched','testing testing testing' FROM DUAL;

合并

MERGE INTO temp dst
USING (
  WITH ordered_words ( rn, id, word ) AS (
    SELECT ROW_NUMBER() OVER ( ORDER BY LENGTH( word ) ASC, word DESC ),
           id,
           word
    FROM   temp
  ),
  sentences_with_ids ( rid, sentence, rn ) AS (
    SELECT ROWID,
           sentence,
           ( SELECT COUNT(*) + 1 FROM ordered_words )
    FROM   temp
  UNION ALL
    SELECT s.rid,
           REGEXP_REPLACE(
             REGEXP_REPLACE(
               s.sentence,
               '(^|\W)' || w.word || '($|\W)',
               '\1${'|| w.id ||'}\2'
              ),
             '(^|\W)' || w.word || '($|\W)',
             '\1${' || w.id || '}\2'
           ),
           s.rn - 1
    FROM   sentences_with_ids s
           INNER JOIN ordered_words w
           ON ( s.rn - 1 = w.rn ) 
  ),
  sentences_with_words ( rid, sentence, rn ) AS (
    SELECT rid,
           sentence,
           ( SELECT COUNT(*) + 1 FROM ordered_words )
    FROM   sentences_with_ids
    WHERE  rn = 1
  UNION ALL
    SELECT s.rid,
           REPLACE(
             s.sentence,
             '${' || w.id || '}',
             'http://localhost/' || w.id || '/<u>' || w.word || '</u>'
           ),
           s.rn - 1
    FROM   sentences_with_words s
           INNER JOIN ordered_words w
           ON ( s.rn - 1 = w.rn ) 
  )
  SELECT rid, sentence
  FROM   sentences_with_words
  WHERE  rn = 1
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
  UPDATE
  SET    sentence = src.sentence;

输出

ID | WORD                    | SENTENCE                                                                                                                                                                                                  
-: | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1 | automation testing      | automtestingation http://localhost/2/<u>testing</u> is popular kind of http://localhost/2/<u>testing</u>                                                                                                  
 2 | testing                 | http://localhost/3/<u>manual testing</u>                                                                                                                                                                  
 3 | manual testing          | this is an old method of http://localhost/2/<u>testing</u>                                                                                                                                                
 4 | punctuation             | http://localhost/1/<u>automation testing</u>,http://localhost/3/<u>manual testing</u>,http://localhost/4/<u>punctuation</u>,automanual http://localhost/2/<u>testing</u>-http://localhost/2/<u>testing</u>
 5 | B-number analysis       | http://localhost/6/<u>B-number analysis table</u>                                                                                                                                                         
 6 | B-number analysis table | http://localhost/2/<u>testing</u> http://localhost/5/<u>B-number analysis</u>                                                                                                                             
 7 | Not Matched             | http://localhost/2/<u>testing</u> http://localhost/2/<u>testing</u> http://localhost/2/<u>testing</u>                                                                                                     

db <>提琴here


更新

在单词中转义任何特殊的正则表达式字符:

MERGE INTO temp dst
USING (
  WITH ordered_words ( rn, id, word, regex_safe_word ) AS (
    SELECT ROW_NUMBER() OVER ( ORDER BY LENGTH( word ) ASC, word DESC ),
           id,
           word,
           REGEXP_REPLACE( word, '([][)(}{|^$\.*+?])', '\\\1' )
    FROM   temp
  ),
  sentences_with_ids ( rid, sentence, rn ) AS (
    SELECT ROWID,
           sentence,
           ( SELECT COUNT(*) + 1 FROM ordered_words )
    FROM   temp
  UNION ALL
    SELECT s.rid,
           REGEXP_REPLACE(
             REGEXP_REPLACE(
               s.sentence,
               '(^|\W)' || w.regex_safe_word || '($|\W)',
               '\1${'|| w.id ||'}\2'
              ),
             '(^|\W)' || w.regex_safe_word || '($|\W)',
             '\1${' || w.id || '}\2'
           ),
           s.rn - 1
    FROM   sentences_with_ids s
           INNER JOIN ordered_words w
           ON ( s.rn - 1 = w.rn ) 
  ),
  sentences_with_words ( rid, sentence, rn ) AS (
    SELECT rid,
           sentence,
           ( SELECT COUNT(*) + 1 FROM ordered_words )
    FROM   sentences_with_ids
    WHERE  rn = 1
  UNION ALL
    SELECT s.rid,
           REPLACE(
             s.sentence,
             '${' || w.id || '}',
             'http://localhost/' || w.id || '/<u>' || w.word || '</u>'
           ),
           s.rn - 1
    FROM   sentences_with_words s
           INNER JOIN ordered_words w
           ON ( s.rn - 1 = w.rn ) 
  )
  SELECT rid, sentence
  FROM   sentences_with_words
  WHERE  rn = 1
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
  UPDATE
  SET    sentence = src.sentence;

输出

ID | WORD                    | SENTENCE                                                                                                                                                                                                  
-: | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1 | automation testing      | automtestingation http://localhost/2/<u>testing</u> is popular kind of http://localhost/2/<u>testing</u>                                                                                                  
 2 | testing                 | http://localhost/3/<u>manual testing</u>                                                                                                                                                                  
 3 | manual testing          | this is an old method of http://localhost/2/<u>testing</u>                                                                                                                                                
 4 | punctuation             | http://localhost/1/<u>automation testing</u>,http://localhost/3/<u>manual testing</u>,http://localhost/4/<u>punctuation</u>,automanual http://localhost/2/<u>testing</u>-http://localhost/2/<u>testing</u>
 5 | B-number analysis       | http://localhost/6/<u>B-number analysis table</u>                                                                                                                                                         
 6 | B-number analysis table | http://localhost/2/<u>testing</u> http://localhost/5/<u>B-number analysis</u>                                                                                                                             
 7 | Not Matched             | http://localhost/2/<u>testing</u> http://localhost/2/<u>testing</u> http://localhost/2/<u>testing</u>                                                                                                     
 8 | ^[($                    | http://localhost/2/<u>testing</u> characters http://localhost/8/<u>^[($</u> that need escaping in a regular expression                                                                                    

db <>提琴here