Oracle在第一个和最后一个空格之间替换文本

时间:2010-06-05 16:36:20

标签: sql oracle

以下是列名为Ships的表数据。

+--------------+
Ships          |
+--------------+
Duke of north  |
---------------+
Prince of Wales|
---------------+
Baltic         |
---------------+

用符号替换第一个和最后一个空格(不包括这些空格)之间的所有字符 星号(*)。星号的数量必须等于替换的字符数。

4 个答案:

答案 0 :(得分:4)

正则表达式是你的朋友:)

首先匹配空格,然后是任何其他字符,以空格结尾。 然后将其替换为包含起始和尾随空格的字符串,并在其间添加一串星号。

星号字符串是通过右边填充一个星号和另外的星号到适当的长度来制作的。该长度是匹配的正则表达式的长度减去前导/尾随空格的两个字符。

select regexp_replace(column_value,' .* ', 
          ' '||rpad('*',length(regexp_substr(column_value,' .* '))-2,'*')||' ')
from table(sys.dbms_debug_vc2coll(
       'Duke of north','Prince of Wales','Baltic','what if two spaces'));

Duke ** north
Prince ** Wales
Baltic
what ****** spaces

答案 1 :(得分:2)

这真的闻起来像家庭作业。因此,我不会向您提供全部优惠,而是指向正确的方向:

查看InStr功能。特别是它的第3和第4个参数,允许您从第X个字符开始搜索和/或搜索第Y个字符。

编辑:如果有人在搜索中找到此主题并希望找到适用于旧版本Oracle的解决方案,那么我就是这样做的。 (我把它作为评论发布到另一篇文章,但作者因某些莫名其妙的原因删除了他的答案o_O)

SELECT case
         when InStr(Name, ' ', 1) > 0 and
              InStr(Name, ' ', 1) <> InStr(Name, ' ', -1) then
           SubStr(Name, 1, InStr(Name, ' ', 1) - 1) ||
           lPad('*', InStr(Name, ' ', -1) - InStr(Name, ' ', 1) + 1, '*') ||
           SubStr(Name, InStr(Name, ' ', -1) + 1)
         else
           Trim(Name)
       end
FROM   SomeTable

答案 2 :(得分:0)

虽然原始问题中的数据只有一个单词,但在单词的第一个和最后一个之间可能有多个单词。例如:“此是一个包含多个字词的示例”

我认为解决方案应该是这样的,它也可以处理所有这些......

无论如何,这是另一种解决方案:

With
I As(
    /*Serves as an input parameter*/
    Select 'This is an example with more than one word' Str From Dual
)
,D As(
    /*Split words into rows*/
    Select RegExp_SubStr(Str,'[^ ]+',1,Level) Word,RowNum Seq,First_value(RowNum) Over(Order By RowNum Desc) L
    From I
    Connect By RegExp_SubStr(Str,'[^ ]+',1,Level) Is Not NULL
)
Select
    /*Assemble all together - other than the first and the last word, replace all the rest into "*"*/
    --uncomment the ListAgg statement if using 11g--
    --ListAgg(Decode(Seq,1,Word,L,Word,RegExp_Replace(Word,'.','*')),' ') Within Group(Order By Seq) Statement
    --If using earlier version of Oracle then use the following--
    Trim(RegExp_Replace(XMLAgg(XMLElement(R,Decode(Seq,1,Word,L,Word,RegExp_Replace(Word,'.','*'))||' ') Order By Seq),'</?R>')) Statement
From D
/

输出: This ** ** ******* **** **** **** *** word

答案 3 :(得分:-2)

SELECT a actual_string,
  first_word,
  SUBSTR(output1,1,LENGTH(output1)-LENGTH(SUBSTR(output1,(
  CASE
    WHEN regexp_count(output1,' ')=0
    THEN 0
    ELSE regexp_instr(output1,' ',1,regexp_count(output1,' '))
  END)+1))) middle_words,
  last_word,
  CASE
    WHEN first_word=last_word
    THEN first_word
    ELSE first_word
      ||TRANSLATE(upper(SUBSTR(output1,1,LENGTH(output1)-LENGTH(SUBSTR(output1,(
      CASE
        WHEN regexp_count(output1,' ')=0
        THEN 0
        ELSE regexp_instr(output1,' ',1,regexp_count(output1,' '))
      END)+1)))),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','**************************')
      ||last_word
  END final_result
FROM
  (SELECT a,
    CASE
      WHEN SUBSTR(a,1,regexp_instr(a,' ',1)) IS NULL
      THEN a
      ELSE SUBSTR(a,1,regexp_instr(a,' ',1))
    END first_word,
    SUBSTR(a,(
    CASE
      WHEN regexp_count(a,' ')=0
      THEN 0
      ELSE regexp_instr(a,' ',1,regexp_count(a,' '))
    END)+1) last_word,
    SUBSTR(a, LENGTH(
    CASE
      WHEN SUBSTR(a,1,regexp_instr(a,' ',1)) IS NULL
      THEN a
      ELSE SUBSTR(a,1,regexp_instr(a,' ',1))
    END)+1, LENGTH(SUBSTR(a,(
    CASE
      WHEN regexp_count(a,' ')=0
      THEN 0
      ELSE regexp_instr(a,' ',1,regexp_count(a,' '))
    END)+1))-2) middle_words,
    CASE
      WHEN regexp_instr(a,' ',1)         +1>1
      THEN SUBSTR(a,regexp_instr(a,' ',1)+1,
        CASE
          WHEN regexp_count(a,' ')=0
          THEN 0
          ELSE regexp_instr(a,' ',1,regexp_count(a,' '))
        END )
      ELSE a
    END output1--,
  FROM
    ( SELECT 'Duke of north' a FROM dual

    UNION

    SELECT 'Prince of Wales' a FROM dual

    UNION

    SELECT 'Baltic' a FROM dual

    UNION

    SELECT 'what if two spaces' a FROM dual

    UNION

    SELECT 'what if two or spaces' a FROM dual
    )
  )