Почему REGEXP_LIKE не распознаёт границы слов?
Возникла проблема с поиском границ слов с помощью REGEXP_LIKE.
Следующий запрос возвращает одну строку, как и ожидалось:
select 1 from dual
where regexp_like('DOES TEST WORK HERE','TEST');
But I want to match on word boundaries as well. So, adding the "\b" characters gives this query
Но хотелось бы, чтобы поиск осуществлялся и по границам слов. То есть, если добавить символы \b в следующий запрос:
select 1 from dual
where regexp_like('DOES TEST WORK HERE','\bTEST\b');
То он больше не вернёт одну ожидаемую запись.
Какие есть идеи?
Свободный перевод вопроса Oracle REGEXP_LIKE and word boundaries от участника @Greg Reynolds
Ответы (2 шт):
Полагаю, что надо сделать так:
select 1 from dual
where regexp_like ('does test work here', '(^|\s)test(\s|$)');
Это потому, что \b не упоминается в списке Perl-influenced Extensions in Oracle Regular Expressions.
Символ \s обеспечивает, чтобы искомое слово начиналася и заканчивалось пробелом. Однако этого недостаточно, так как искомое слово может оказаться в самом начале или конце полной строки. Поэтому использую альтернативу (на это указывает символ |) ^ для начала строки и $ для конца строки.
Обновление (спустя 3 года+) ...
Так совпало, что недсавно потребовалась эта функциональность, и кажется, что еще лучше регулярное выражение (^|\s|\W)test($|\s|\W) (см. блог Отсутствующий специальный символ регулярного выражения \b в Oracle).
Свободный перевод ответа от участника @René Nyffenegger
Самый короткий шаблон, который заменит границу слова \b, т.е. найдёт целое слово, это:
(^|\W)test($|\W)
См. воспроизводимый пример на regex101.
Подробней
(^|\W)- группа захвата, совпадающая либо с^- начало строки|- или\W- несловарный символ
test- само слово($|\W)- группа захвата, совпадающая либо с$- конец строки|- или\W- несловарный символ.
Заметьте, что \W соответствует любым символам, кроме букв, цифр и _. Если надо найти слово, которое заключено между _ (подчеркиваниями), то нужен немного другой шаблон:
(^|[^[:alnum:]])test($|[^[:alnum:]])
Отрицаемое выражение во внутренних скобках [^[:alnum:]] совпадёт с любым символом (куда входит _), кроме алфавитно-цифровых, поэтому _test_ будет найден этим шаблоном.
См. воспроизводимый пример на regex101.
Свободный перевод ответа от участника @Wiktor Stribiżew