2015-04-06 4 views
2

Я нашел неожиданный результат при использовании regexp_replace, чтобы объединить строку в конце другой строки, как упражнение в использовании regexp_replace для этого. Я привожу его, чтобы не только понять, почему, но и сообщить людям об этом, возможно, неожиданном результате.Объяснение неожиданного результата regexp_replace

Рассмотрите это заявление, в котором намерение заключается в том, чтобы зафиксировать «примечание 2» в конце строки «Примечание 1». Мое намерение состояло в том, чтобы сгруппировать всю линию, а затем сцепить новую строку в конец:

select regexp_replace('note 1', '(.*)', '\1' || ' note 2') try_1 from dual; 

Но посмотрите на результат:

TRY_1    
-------------------- 
note 1 note 2 note 2 

Нота получает повторяется дважды! Зачем?

Если изменить шаблон, чтобы включить в начало строки и конец строки якорей, он работает, как ожидалось:

select regexp_replace('note 1', '^(.*)$', '\1' || ' note 2') try_2 from dual; 

TRY_2   
------------- 
note 1 note 2 

Почему что-то изменить?

РЕДАКТИРОВАТЬ: пожалуйста, ознакомьтесь с пояснениями Полянка-З ниже. Я хотел бы добавить, если я изменил первый пример на использование плюса (совпадение 1 или более вхождений предыдущего символа) в отличие от звездочки (для 0 или более вхождений предыдущего символа), он работает так, как ожидалось:

select regexp_replace('note 1', '(.+)', '\1' || ' note 2') try_3 from dual; 

TRY_3   
------------- 
note 1 note 2 

ответ

3

согласно Oracle Documentation:

По умолчанию, функция возвращает source_char все вхождения регулярного выражения заменены строку_замены.

Ключ в наличии каждое происхождение. .* соответствует пустой строке, а механизм Oracle regexp сначала соответствует всей строке, а затем следующую пустую строку. Добавляя якоря, вы устраняете это. В качестве альтернативы вы можете указать параметр вхождения для связанной документации.

+0

Можете ли вы объяснить, откуда берется «пустая строка»? Спасибо –

+1

Звездочка указывает, что предыдущий атом регулярного выражения встречается ноль или более раз. Учитывая ваше общее регулярное выражение, это означает, что нулевые совпадения - пустая строка - действительное совпадение. 'regexp_replace' применяет ваш regexp один раз, сопоставляя всю строку (см. жадные против неживых в терминах регулярного выражения), а затем ищет другое совпадение, начиная с конца предыдущего совпадения. Конец предыдущего совпадения после последнего символа, оставив пустую строку. –

+0

Очень интересно! Я заменил шаблон «. *» На «. +» (Плюс для соответствия 1 или более, в отличие от звездочки, значения 0 или более) в первом примере, и он работает так, как ожидалось! Спасибо Politank-Z! –

Смежные вопросы