匹配第三组后,它开始从 text3 中寻找下一个匹配;尾随 .* 被有效忽略。对于较早的组,这就是您想要的 - 否则第一组的尾随 .* 将包含字符串的其余部分,您将丢失其他组。当它从 text3 开始时,它找不到另一个匹配项,因此返回原始值(当时)。
如果值始终以逗号分隔,那么您可以在匹配项中包含逗号或字符串结尾锚点,以使其包含剩余的文本(直到空格),但不在 \1 中:
select regexp_replace('ST1_12 text1, KG32_1 text2, VI7_08 text3','.*?(\w+\d+_\d+).*(,|$)', '\1,') c1
from dual;
ST1_12,KG32_1,VI7_08,
您可以使用修剪功能去除尾随逗号:
select rtrim(regexp_replace('ST1_12 text1, KG32_1 text2, VI7_08 text3','.*?(\w+\d+_\d+).*(,|$)','\1,', 1, 0, null),
',') as c1
from dual;
ST1_12,KG32_1,VI7_08
另一个不依赖于现有逗号的选项是将字符串拆分为多个值:
select regexp_substr('ST1_12 text1, KG32_1 text2, VI7_08 text3', '(\w+\d+_\d+)', 1, level, null, 1) as c1
from dual
connect by level <= regexp_count('ST1_12 text1, KG32_1 text2, VI7_08 text3', '(\w+\d+_\d+)');
ST1_12
KG32_1
VI7_08
然后将它们重新聚合在一起:
select listagg(
regexp_substr('ST1_12 text1, KG32_1 text2, VI7_08 text3', '(\w+\d+_\d+)', 1, level, null, 1),
',') within group (order by level) as c1
from dual
connect by level <= regexp_count('ST1_12 text1, KG32_1 text2, VI7_08 text3', '(\w+\d+_\d+)');
ST1_12,KG32_1,VI7_08
db<>fiddle