Regexp_substr найти строку, не соответствующую группе символов

У меня есть строка типа mystr = 'value1~|~value2~|~ ... valuen". Мне это нужно как один столбец, разделенный на такие строки:

value1
value2
...
valuen

я пытаюсь это

select regexp_substr(mystr, '[^(~\|~)]', 1 , lvl) from dual, (select level as lvl from dual connect by level <= 5);

Проблема в том, что ~|~ не рассматривается как группа, если я добавляю ~ в любом месте строки, она разделяется; также () рассматриваются как разделители.

Любая помощь высоко ценится! Спасибо! ~|~


person C.B.Luca    schedule 29.08.2017    source источник
comment
Хранить такие значения не рекомендуется. Читать о нормализации   -  person Jens    schedule 29.08.2017
comment
Значения не хранятся таким образом. Это только упрощенный пример.   -  person C.B.Luca    schedule 29.08.2017


Ответы (3)


Быстрое и грязное решение:

with t as (
select rtrim(regexp_substr('value1~|~value2~|~value3~|~value4', '(.+?)($|~\|~)', 1,level,''),'~|~')value  from dual connect by level<10
) select * from t where value is not null;
person wolfrevokcats    schedule 29.08.2017

[] означает совпадение одного символа, а [^] означает совпадение одного символа, который не соответствует ни одному из содержащихся символов.

Таким образом, [^(~\|~)] будет соответствовать любому символу, который не является ( или ~ или \ или | или ~ (снова) или ).

То, что вам нужно, это совпадение, которое завершается вашим разделителем:

SELECT REGEXP_SUBSTR(
         mystr,
         '(.*?)(~\|~)',
         1,
         LEVEL,
         NULL,
         1
       )
FROM   DUAL
CONNECT BY LEVEL < REGEXP_COUNT( mystr, '(.*?)(~\|~)' );

(или, если у вас нет совпадений с нулевой шириной, вы можете использовать регулярное выражение '(.+?)(~\|~)' и <= в предложении CONNECT BY.)

person MT0    schedule 29.08.2017

Это будет анализировать список с разделителями, а формат регулярного выражения будет обрабатывать элементы списка NULL, если они встречаются, как показано в примере.

SQL> with tbl(str) as (
      select 'value1~|~value2~|~~|~value4' from dual
    )
    select regexp_substr(str, '(.*?)(~\|~|$)', 1, level, NULL, 1) parsed
    from tbl
    connect by level <= regexp_count(str, '~\|~')+1;

PARSED
--------------------------------
value1
value2

value4

SQL>
person Gary_W    schedule 29.08.2017