2010-06-05 2 views
0

Вот данные таблицы с именем столбца как «Корабли».Oracle, заменяющий текст между первым и последним пробелами

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

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

+1

Является ли это 'homework' вопрос? Если это так, пометьте его как таковой. – VeeArr

ответ

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 
2

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

Проверьте функцию InStr. Espcecially его 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

Эй, его не вопрос HW, это был сложный вопрос, который я пробовал целый день, но все же я еще не нашел ответа. Я никогда не отправляю вопрос в переполнение стека, прежде чем пытаться его решить достаточно много раз. – user338292

-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 
    ) 
) 
+1

На выходе есть дополнительные пробелы. Я понимаю, что всегда есть нечто большее, чем один способ сделать что-то, но я думаю, что этот код слишком длинный и сложный, чтобы быть полезным другим. Если есть смысл использовать этот код, в отличие от принятого ответа, вы можете его объяснить. –

+0

, пожалуйста, старайтесь избегать ответов только с кодом, добавьте некоторое объяснение в свой код для более качественного ответа – Dreen

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

Смежные вопросы