从字符串中删除特定单词

时间:2014-02-03 12:18:14

标签: sql regex oracle replace

我正在使用oracle10g

我想从句子中删除所有出现的特定单词,但我不想删除包含a-z或A-Z之间其他字符的任何其他单词。

例如,以下是我要删除some的句子:

some text, 123 someone, another text some1

预期输出

 text, 123 someone, another text

请注意,如果some字词some以及A-Z之前或之后a-z以外的任何其他字词,我还要删除some字。< / p>

这是我到目前为止所尝试的:

select replace('some text, 123 someone, another text some1','some','') 
from dual;

我得到了输出:

 text, 123 one, another text 1

在上面的输出中,我希望someone不被替换,some1应该完全替换。

我应该如何实现这一目标?任何建议将不胜感激。

编辑:为了清楚起见,这是我正在寻找的另一个例子:

some other text someone other text, someB some1 some.
输出应该是:

 other text someone other text, someB 

上述句子someB未被删除,因为它在a-z之间有字符 some1some.被移除,因为a-z之间没有字符。

EDIT2

如果我使用正则表达式:

select REGEXP_REPLACE('some text, 123 someone, another text some1','[^a-zA-Z]','')
from dual

我得到了输出:

sometextsomeoneanothertextsome

预期产出:

sometextsomeoneanothertext

请注意,我希望some1也可以从字符串中移除,因为它包含除A-Z以外的其他字符。

使用regex的答案也很受欢迎。

5 个答案:

答案 0 :(得分:3)

由于在Oracle正则表达式实现中缺乏对lookbehind/lookaheadword boundary(\b)的支持,似乎无法满足单REGEXP_REPLACE次调用中的所有要求。特别是对于大小写,pointed out by Egor Skriptunoff:模式匹配,一个接一个地跟在它们之间只有一个分隔符,如some some some some ...

如果没有这种情况,可以将所有此类字符串与此调用匹配:

regexp_replace(
  source_string,                                       -- source string
  '([^[:alnum:]]|^)((\d)*some(\d)*)([^[:alnum:]]|$)',  -- pattern
  '\1\5',                                              -- leave separators in place
  1,                                                   -- start from beginning
  0,                                                   -- replace all occurences
  'im'                                                 -- case-insensitive and multiline 
);

图案部分:

(                -- start of Group #1
  [^[:alnum:]]   -- any non-alphanumeric character 
  |              -- or 
  ^              -- start of string or start of line 
)                -- end of Group #1
(                -- start of Group #2
  (              -- start of Group #3 
    \d           -- any digit
  )              -- end of Group #3
  *              -- include in previous group zero or more consecutive digits
  some           -- core string to match
  (              -- start of group #4
    \d           -- any digit
  )              -- end of group #4  
  *              -- include in previous group zero or more consecutive digits
)                -- end of Group #2
(                -- start of Group #5
  [^[:alnum:]]   -- any non-alphanumeric character 
  |              -- or
  $              -- end of string or end of line
)                -- end of Group #5

因为匹配模式中包含用于匹配的分隔符(组#1和组#5),它将在成功匹配时从源字符串中删除,因此我们需要通过在第三个regexp_replace参数中指定来恢复此部分。 / p>

基于此解决方案,可以在循环中替换所有甚至重复的事件。

例如,您可以定义类似的函数:

create or replace function delete_str_with_digits(
  pSourceString in varchar2, 
  pReplacePart  in varchar2  -- base string (like 'some' in question)
)
  return varchar2
is
  C_PATTERN_START constant varchar2(100) := '([^[:alnum:]]|^)((\d)*';
  C_PATTERN_END   constant varchar2(100) := '(\d)*)([^[:alnum:]]|$)';

  vPattern         varchar2(4000);
  vCurValue        varchar2(4000);
  vPatternPosition binary_integer;
begin

  vPattern := C_PATTERN_START || pReplacePart || C_PATTERN_END;
  vCurValue := pSourceString;

  vPatternPosition := regexp_instr(vCurValue, vPattern);

  while(vPatternPosition > 0) loop
    vCurValue := regexp_replace(vCurValue, vPattern,'\1\5',1,0,'im');
    vPatternPosition := regexp_instr(vCurValue, vPattern);
  end loop;

  return vCurValue;  

end;

并将其与SQL或其他PL / SQL代码一起使用:

SELECT 
  delete_str_with_digits(
    'some text, -> awesome <- 123 someone, 3some3
     line of 7 :> some some some some some some some <
222some  another some1? some22 text 0some000', 
    'some'
  )  as result_string
FROM 
  dual

<强> SQLFiddle example

答案 1 :(得分:2)

这是一种不使用正则表达式的方法:

select trim(replace(' '||'some text, 123 someone, another text some1'||' ',
                    ' some ',' '
                   ) 
           )
from dual;

答案 2 :(得分:1)

您可以使用REGEXP_REPLACE功能,如下所示

SELECT REGEXP_REPLACE('some text, 123 someone, another text some1', '(^|\s)some(^|\s)', '')
FROM dual;

SQL Fiddle Demo

答案 3 :(得分:1)

使用REGEX_REPLACE()作为

SELECT REGEXP_REPLACE('some other text someone other text, someB some1 some.', '(some\s|some\d|some[.])','')
FROM dual;

SQL Fiddle Demo

希望这会有所帮助。如果有帮助,请将其标记为答案:)

如果您想要除.以外的任何其他字符,只需将其添加到上一个[],如果您还要匹配某些#,那么只需将其添加到.,就像这样[.#]

答案 4 :(得分:1)

像这样的东西

SELECT REGEXP_REPLACE('some text, 123 someone, another text some1 some@, SOMEone SoME1', 
                      '(some\d|some[^[:alnum:]]|some$)','',1,0,'i')
FROM dual;

输出:

text, 123 someone, another text , SOMEone

以下是模式和选项的解释:

  1. some\d - “some”一词后跟任何数字。
  2. some[^[:alnum:]] - 单词“some”后跟任何非字母数字字符。 ^代表否定,[:alnum:]代表字母数字。基本上,[^[:alnum:]][[:alnum:]]相反。
  3. some$如果字符串以“some”结尾。
  4. 1,0,'i' - 从第一次出现1开始,然后是所有出现0且不区分大小写的i