Поведение подгруппы Regex с пробелом и без - PullRequest
1 голос
/ 09 июля 2019

Скажем, задача состояла в том, чтобы добавить последние цифры в коде продукта к себе с дефисом между исходным и добавленным числами (чисто для экспериментов).

Я хотел бы понять, почему необходимо включить пробелв следующем примере:

with foo ( prod )                         
as ( values ('MYPRODUCT 123'))            
select                                    
 'dot aster space' as test_type,          
 '''(.* (\d+))'',''$1-$2''' as the_regex, 
 regexp_replace(prod,'(.* (\d+))','$1-$2')
from foo                                  
 UNION ALL                                
select                                    
 'dot aster no space',                    
 '''(.*(\d+))'',''$1-$2''',               
 regexp_replace(prod,'(.*(\d+))','$1-$2') 
from foo                                  

Результат

TEST_TYPE           THE_REGEX             REGEXP_REPLACE   
dot aster space     '(.* (\d+))','$1-$2'  MYPRODUCT 123-123
dot aster no space  '(.*(\d+))','$1-$2'   MYPRODUCT 123-3  

Я бы ожидал, что, поскольку точка соответствует любому символу, включая пробел, два регулярных выражения будут иметь одинаковый результат.

Однако, даже принимая это, я не могу понять, почему во второй группе фиксируются только последние 3.

Спасибо.

1 Ответ

2 голосов
/ 09 июля 2019

Это вопрос жадности.

с регулярным выражением

'(. * (\ D +))'

Вы явно просите пробел перед цифрами, поэтому \ d + получит 3 цифры.

с регулярным выражением

'(. * (\ D +)) * * 1014

точка. * Займет столько символов, сколько может, прежде чем сопоставить цифру или более. Таким образом. * Будет соответствовать 'MYPRODUCT 12', а \ d + будет соответствовать '3'.

Решение: не жадный квантификатор '?'. Регулярное выражение будет

'(. *? (\ D +))'

и он будет соответствовать максимальным цифрам для \ d +, а затем для остальных. *

...