Поради липса на поддръжка за lookbehind/lookahead
и граница на думата(\b
)
в изпълнението на регулярен израз в Oracle изглежда невъзможно да се изпълнят всички изисквания в един REGEXP_REPLACE
повикване. Специално за случай, посочен от Егор Скриптунов
:съвпадения на шаблони, следвани едно по едно само с един разделител между тях като some some some some ...
.
Без този случай е възможно да се съпоставят всички такива низове с това извикване:
regexp_replace(
source_string, -- source string
'([^[:alnum:]]|^)((\d)*some(\d)*)([^[:alnum:]]|$)', -- pattern
'\1\5', -- leave separators in place
1, -- start from beginning
0, -- replace all occurences
'im' -- case-insensitive and multiline
);
Части на шаблона:
( -- start of Group #1
[^[:alnum:]] -- any non-alphanumeric character
| -- or
^ -- start of string or start of line
) -- end of Group #1
( -- start of Group #2
( -- start of Group #3
\d -- any digit
) -- end of Group #3
* -- include in previous group zero or more consecutive digits
some -- core string to match
( -- start of group #4
\d -- any digit
) -- end of group #4
* -- include in previous group zero or more consecutive digits
) -- end of Group #2
( -- start of Group #5
[^[:alnum:]] -- any non-alphanumeric character
| -- or
$ -- end of string or end of line
) -- end of Group #5
Тъй като разделителите, използвани за съпоставяне (Група #1 и Група #5), включени в шаблона за съвпадение, те ще бъдат премахнати от изходния низ при успешно съвпадение, така че трябва да възстановим тези части, като посочим в третия regexp_replace
параметър.
Въз основа на това решение е възможно да се заменят всички, дори повтарящи се събития в рамките на един цикъл.
Например, можете да дефинирате функция като тази:
create or replace function delete_str_with_digits(
pSourceString in varchar2,
pReplacePart in varchar2 -- base string (like 'some' in question)
)
return varchar2
is
C_PATTERN_START constant varchar2(100) := '([^[:alnum:]]|^)((\d)*';
C_PATTERN_END constant varchar2(100) := '(\d)*)([^[:alnum:]]|$)';
vPattern varchar2(4000);
vCurValue varchar2(4000);
vPatternPosition binary_integer;
begin
vPattern := C_PATTERN_START || pReplacePart || C_PATTERN_END;
vCurValue := pSourceString;
vPatternPosition := regexp_instr(vCurValue, vPattern);
while(vPatternPosition > 0) loop
vCurValue := regexp_replace(vCurValue, vPattern,'\1\5',1,0,'im');
vPatternPosition := regexp_instr(vCurValue, vPattern);
end loop;
return vCurValue;
end;
и го използвайте с SQL или друг PL/SQL код:
SELECT
delete_str_with_digits(
'some text, -> awesome <- 123 someone, 3some3
line of 7 :> some some some some some some some <
222some another some1? some22 text 0some000',
'some'
) as result_string
FROM
dual