REGEXP_REPLACE заменяет текст тем же текстом в нижнем регистре

Я пытаюсь использовать REGEXP_REPLACE в PL/SQL заменить некоторый текст тем же текстом в нижнем регистре. На самом деле, правило, что я хочу, чтобы весь текст между "()" у которого только один символ в нижнем регистре.

Вот пример:

SELECT REGEXP_REPLACE(
  'i want what what is between <> in lower case : I am a test(E) (A) (HELLO)'
  , '(\(\D\))', '<\1>'
) FROM DUAL

Результат:

I want what is between <> in lower case : I am a test(e) (a) (HELLO)

или это потому, что я немного запутался в своих упражнениях:

I want what is between <> in lower case : I am a test<(e)> <(a)> (HELLO)

Как я могу получить мой текст в нижнем регистре? Я пытался несколькими способами, но я не могу выйти с этим. Я не знаю, что сказать REGEXP_REPLACE класть "\1" содержание в нижнем регистре.

Спасибо вам за вашу помощь.

С наилучшими пожеланиями. МИЗ

2 ответа

Oracle11g) Вот как заменить первое вхождение:

использование REGEXP_instr а также REGEXP_substr иметь возможность подать заявку lower к подобранному образцу

 SELECT substr(it, 1  , REGEXP_instr( it,  '(\(\D\))')-1)
     ||lower(          REGEXP_substr(it,  '(\(\D\))')  )
     ||substr(it,      REGEXP_instr( it,  '(\(\D\))')+3, length(it))
FROM (SELECT 'i want what what is between <> in lower case : I am a test(E) (A) (HELLO)' it from dual) ;

и если ты хочешь странного <> вокруг него:

 SELECT substr(it, 1  , REGEXP_instr( it,  '(\(\D\))')-1) 
 || '<'
     ||lower(          REGEXP_substr(it,  '(\(\D\))')  )
 || '>'
     ||substr(it,      REGEXP_instr( it,  '(\(\D\))')+3, length(it))
FROM (SELECT 'i want what what is between <> in lower case : I am a test(E) (A) (HELLO)' it from dual) ;

Я думаю, что вы не можете иметь рекурсивное регулярное выражение в Oracle. Так что если вы хотите иметь возможность заменить 2 вхождения:

SELECT substr(rit, 1 , REGEXP_instr( rit,  '(\([[:upper:]]{1}\))')-1) 
     ||lower(          REGEXP_substr(rit,  '(\([[:upper:]]{1}\))')  )
     ||substr(rit,     REGEXP_instr( rit,  '(\([[:upper:]]{1}\))')+3, length(rit))
from (
(SELECT substr(it, 1 , REGEXP_instr( it,  '(\([[:upper:]]{1}\))')-1) 
     ||lower(          REGEXP_substr(it,  '(\([[:upper:]]{1}\))')  )
     ||substr(it,      REGEXP_instr( it,  '(\([[:upper:]]{1}\))')+3, length(it))  rit
FROM (SELECT 'i want what what is between <> in lower case : I am a test(E) (A) (HELLO)' it from dual))
) ;

(+ Я заменяю \D от [[:upper:]]{1} что точнее)

Для плохого это должно быть такой сложной проблемой! Похоже, это будет легко.

Чтобы обработать переменное число вхождений шаблона, вам нужно перебрать строку, ища их. Может быть, кто-то придумает подходящее решение, используя CONNECT BY или что-то, но в то же время, и так как вы используете PL/SQL, почему бы вам не перейти на old-school и создать функцию, которая это делает? Возможно, его будет проще поддерживать, и он будет заключен в многократно используемую единицу, доступную для всех пользователей. Передайте строку и верните очищенную версию.

SQL> select lower_single_letters('I want what is between in lower case : I am a test(E) (A) (HELLO)') text
    from dual;

TEXT
--------------------------------------------------------------------------------
I want what is between in lower case : I am a test(e) (a) (HELLO)

SQL>

Вот пример кода, так как я хотел пример для использования в моем пакете утилит:

CREATE OR REPLACE function lower_single_letters(string_in varchar2) return varchar2 is 
  tmp_string             varchar2(1000) := string_in;         -- Holds the string
  regex_pattern constant varchar2(20)   := '\([[:upper:]]\)'; -- Pattern to look for '(A)'
  letter_offset          integer;                             -- Offset of the pattern
  letter                 varchar2(1);                         -- The letter to lower()
BEGIN
  -- Loop while the pattern is found in the string passed in
  while regexp_like(tmp_string, regex_pattern)
  loop
    -- Get the offset in the string
    letter_offset := regexp_instr(tmp_string, regex_pattern)+1;
    -- Get the letter
    letter        := substr(tmp_string, letter_offset, 1);
    -- Replace it in the string
    tmp_string    := regexp_replace(tmp_string, '.', lower(letter), 1, letter_offset);
  end loop;
  -- Return it when the pattern is no longer found
  return(tmp_string);
END lower_single_letters;
Другие вопросы по тегам