REGEXP SUBSTR, где разделителем является комбинация из 2 или более символов.

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

Пожалуйста, найдите запрос, который я пробовал ниже:

select REGEXP_SUBSTR('123$@45$6$@789','[^$@]+',1,2) from dual

Необходимый вывод:

45$6

Вывод:

45

Я понимаю, что это легко возможно с помощью пользовательских функций [с INSTR+SUBSTR], однако я ищу ответ и объяснение с помощью REGEXP_SUBSTR.

Заранее спасибо.


person pOrinG    schedule 03.10.2017    source источник


Ответы (1)


Не так... Скорее:

select REGEXP_SUBSTR('123$@45$6$@789','(.*?)(\$@|$)', 1, 2, null, 1) from dual;

Обратите внимание на \$ в коде; $ означает конец строки, поэтому, если вы имеете в виду буквальный символ знака доллара, вы должны его экранировать. В этом решении используется концепция «группы захвата» — см. документацию Oracle для REGEXP_SUBSTR(), если вы не знакомы. Первая группа захвата — (.*?) — все, что стоит перед разделителем; и на него ссылается шестой (последний) аргумент REGEXP_SUBSTR.

Обратите также внимание, что после первой группы захвата я проверяю либо двухсимвольный разделитель , либо конец строки... который помечен $. Два параметра в круглых скобках, разделенные | (еще один «специальный символ»), представляют собой синтаксис регулярного выражения для «либо... или...».

person mathguy    schedule 03.10.2017
comment
Большое спасибо. Посоветуйте, правильно ли я понимаю. (.*?): точка для любого символа, * для нуля или более вхождений любого символа, что звучит достаточно, однако, если мы оставим его там, тогда он станет жадным поиском и выберет все до конца строки. Таким образом, ? должен сделать поиск нежадным и остановиться в первой точке, где он находит повторение разделителя. Спасибо за совет по экранированию специальных символов и or конца строки, чтобы получить последнее значение с разделителями. - person pOrinG; 03.10.2017
comment
Ваше понимание жадного и нежадного (или ленивого) сопоставления абсолютно правильное. Поскольку мы не можем использовать трюк, который вы хотели использовать (что-то вроде [^;]+), поиск только непрерывных подстрок НЕ-точки с запятой (или любого другого односимвольного разделителя), и вместо этого мы действительно должны использовать .* или .+, пока мы не найдем разделитель , мы ДОЛЖНЫ использовать нежадный поиск. Обратите также внимание на слабость +, а не * - если у вас есть два разделителя сразу друг за другом, это должно представлять NULL; но с оператором + вы полностью их пропустите. Оператор * их тоже ловит. - person mathguy; 03.10.2017
comment
Эта слабость + против * меня очень удивила. Не подумал бы об этом, если бы не столкнулся с проблемой из-за этого. Ценить это. - person pOrinG; 03.10.2017