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;