Oracle заменяет текст между первым и последним пробелами - PullRequest
0 голосов
/ 05 июня 2010

Вот данные таблицы с названием столбца Ships.

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

Заменить все символы между первым и последним пробелами (исключая эти пробелы) символами звездочки (*). Количество звездочек должно быть равно количеству замененных символов.

Ответы [ 4 ]

4 голосов
/ 08 июня 2010

Регулярные выражения - ваш друг:)

Сначала сопоставьте пробел, затем любые другие символы, заканчивающиеся пробелом. Затем замените его строкой, состоящей из начального и конечного пробелов и между ними строкой звездочек.

Строка звездочек создается путем добавления правой звездочки к одной звездочке с дополнительными звездочками соответствующей длины. Эта длина равна длине регулярного выражения минус два символа для начального / конечного пробела.

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
2 голосов
/ 05 июня 2010

Это действительно пахнет домашней работой.Поэтому я не буду предоставлять вам полную сделку, а вместо этого укажу правильное направление:

Проверьте функцию 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
0 голосов
/ 25 июня 2013

Несмотря на то, что данные в исходном вопросе содержали только одно слово между ними, можно иметь более одного слова между первым и последним словом. Например: «Этот является примером с более чем одним словом»

Полагаю, решение должно быть таким, чтобы оно также обрабатывало все это ...

В любом случае, вот другое решение:

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

0 голосов
/ 25 июля 2012
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
    )
  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...