REGEXP_REPLACE 没有发生连续模式替换
Consecutive Pattern replacing is not happening with REGEXP_REPLACE
我有如下字符串
Welcome to the world of the Hackers
我正在尝试使用以下查询替换整个字符串之间列出的字符串的出现,即 of,to,the
,但如果模式是连续的,它就无法正常工作,它会失败。
SELECT regexp_replace( 'Welcome to the world of the Hackers', '( to )|( the )|( of )', ' ' )
FROM dual;
输出:Welcome the world the Hackers
即使模式连续重复,它也不起作用,即
SELECT regexp_replace( 'Welcome to to the world of the Hackers', '( to )|( the )|( of )', ' ' )
FROM dual;
输出:Welcome to world the Hackers
而我的预期输出是:Welcome world Hackers
使用REGEXP_REPLACE
是否有任何alternative/solution?
REGEXP_REPLACE
不匹配作为已匹配模式一部分的第二个模式。当您使用像 |
这样的多模式匹配时,这一点会更加明显。因此,您不能依赖单词边界的空格以这种方式匹配多个模式。一种解决方案可能是拆分和组合字符。这可能不是最好的方法,但仍然有效。我很高兴知道更好的解决方案。
这还假定当原始 string.Also 中有多个空格时,您可以在组合字符串中使用单个空格,不考虑以逗号或分号结尾的单词。对于这种情况,您可以使用 NOT REGEXP_LIKE
而不是 NOT IN
来增强它。
WITH t (id,s)
AS (
SELECT 1 , 'Welcome to the world of the Hackers, you told me these words at the'
FROM DUAL
UNION ALL
SELECT 2, 'The second line.Welcome to the world of the Hackers, you told me these words at the'
FROM DUAL
)
SELECT LISTAGG(word, ' ') WITHIN
GROUP (
ORDER BY w
)
FROM (
SELECT id,
LEVEL AS w
,REGEXP_SUBSTR(s, '[^ ]+', 1, LEVEL) AS word
FROM t CONNECT BY LEVEL <= REGEXP_COUNT(s, '[^ ]+')
AND PRIOR id = id
AND PRIOR SYS_GUID() IS NOT NULL
)
WHERE lower(word) NOT IN (
'to'
,'the'
,'of'
)
GROUP BY id;
您可以使用正则表达式(^|\s+)((to|the|of)(\s+|$))+
:
查询 1:
WITH test_data ( sentence ) AS (
SELECT 'to the of' FROM DUAL UNION ALL
SELECT 'woof breathe toto' FROM DUAL UNION ALL -- has all the words as sub-strings of words
SELECT 'theory of the offer to total' FROM DUAL -- mix of words to replace and words starting with those words
)
SELECT sentence,
regexp_replace(
sentence,
'(^|\s+)((to|the|of)(\s+|$))+',
''
) AS replaced
FROM test_data
| SENTENCE | REPLACED |
|------------------------------|--------------------|
| to the of | (null) | -- All words replaced
| woof breathe toto | woof breathe toto |
| theory of the offer to total | theory offer total |
Why doesn't regexp_replace( 'Welcome to the world of the Hackers', '( to )|( the )|( of )', ' ' )
work with successive matches?
因为正则表达式解析器会在第一个匹配结束后寻找第二个匹配,并且在寻找时不会包括已经解析的字符串部分或替换文本用于后续比赛。
所以第一场比赛将是:
'Welcome to the world of the Hackers'
^^^^
第二个匹配项将查找该匹配项之后的子字符串
'the world of the Hackers'
^^^^
子字符串开头的 'the '
将不会被匹配,因为它没有前导 space 字符(是的,它之前有一个 space 但那是在上一场比赛中匹配,是的,该比赛被 space 替换,但重叠比赛和之前替换的比赛不是正则表达式的工作方式。
所以第二个匹配是剩余子串中间的' of '
。
不会有第三个匹配项,因为剩余的未解析子字符串是:
'the Hackers'
并且,'the '
再次不匹配,因为没有要匹配的前导 space 字符。
我有如下字符串
Welcome to the world of the Hackers
我正在尝试使用以下查询替换整个字符串之间列出的字符串的出现,即 of,to,the
,但如果模式是连续的,它就无法正常工作,它会失败。
SELECT regexp_replace( 'Welcome to the world of the Hackers', '( to )|( the )|( of )', ' ' )
FROM dual;
输出:Welcome the world the Hackers
即使模式连续重复,它也不起作用,即
SELECT regexp_replace( 'Welcome to to the world of the Hackers', '( to )|( the )|( of )', ' ' )
FROM dual;
输出:Welcome to world the Hackers
而我的预期输出是:Welcome world Hackers
使用REGEXP_REPLACE
是否有任何alternative/solution?
REGEXP_REPLACE
不匹配作为已匹配模式一部分的第二个模式。当您使用像 |
这样的多模式匹配时,这一点会更加明显。因此,您不能依赖单词边界的空格以这种方式匹配多个模式。一种解决方案可能是拆分和组合字符。这可能不是最好的方法,但仍然有效。我很高兴知道更好的解决方案。
这还假定当原始 string.Also 中有多个空格时,您可以在组合字符串中使用单个空格,不考虑以逗号或分号结尾的单词。对于这种情况,您可以使用 NOT REGEXP_LIKE
而不是 NOT IN
来增强它。
WITH t (id,s)
AS (
SELECT 1 , 'Welcome to the world of the Hackers, you told me these words at the'
FROM DUAL
UNION ALL
SELECT 2, 'The second line.Welcome to the world of the Hackers, you told me these words at the'
FROM DUAL
)
SELECT LISTAGG(word, ' ') WITHIN
GROUP (
ORDER BY w
)
FROM (
SELECT id,
LEVEL AS w
,REGEXP_SUBSTR(s, '[^ ]+', 1, LEVEL) AS word
FROM t CONNECT BY LEVEL <= REGEXP_COUNT(s, '[^ ]+')
AND PRIOR id = id
AND PRIOR SYS_GUID() IS NOT NULL
)
WHERE lower(word) NOT IN (
'to'
,'the'
,'of'
)
GROUP BY id;
您可以使用正则表达式(^|\s+)((to|the|of)(\s+|$))+
:
查询 1:
WITH test_data ( sentence ) AS (
SELECT 'to the of' FROM DUAL UNION ALL
SELECT 'woof breathe toto' FROM DUAL UNION ALL -- has all the words as sub-strings of words
SELECT 'theory of the offer to total' FROM DUAL -- mix of words to replace and words starting with those words
)
SELECT sentence,
regexp_replace(
sentence,
'(^|\s+)((to|the|of)(\s+|$))+',
''
) AS replaced
FROM test_data
| SENTENCE | REPLACED |
|------------------------------|--------------------|
| to the of | (null) | -- All words replaced
| woof breathe toto | woof breathe toto |
| theory of the offer to total | theory offer total |
Why doesn't
regexp_replace( 'Welcome to the world of the Hackers', '( to )|( the )|( of )', ' ' )
work with successive matches?
因为正则表达式解析器会在第一个匹配结束后寻找第二个匹配,并且在寻找时不会包括已经解析的字符串部分或替换文本用于后续比赛。
所以第一场比赛将是:
'Welcome to the world of the Hackers'
^^^^
第二个匹配项将查找该匹配项之后的子字符串
'the world of the Hackers'
^^^^
子字符串开头的 'the '
将不会被匹配,因为它没有前导 space 字符(是的,它之前有一个 space 但那是在上一场比赛中匹配,是的,该比赛被 space 替换,但重叠比赛和之前替换的比赛不是正则表达式的工作方式。
所以第二个匹配是剩余子串中间的' of '
。
不会有第三个匹配项,因为剩余的未解析子字符串是:
'the Hackers'
并且,'the '
再次不匹配,因为没有要匹配的前导 space 字符。