2016-07-05 7 views
1

Я хочу разделить разделенную запятой строку на свои части с помощью PL/SQL. Он отлично работает с REGEXP_SUBSTR, если в строке нет круглой скобки.Круглый кронштейн REGEXP_SUBSTR

Пример:

select REGEXP_SUBSTR('A;B;C','[^(";")]+',1,1), 
REGEXP_SUBSTR('A;B;C','[^(";")]+',1,2), 
REGEXP_SUBSTR('A;B;C','[^(";")]+',1,3) 
from dual; 

Результат, как ожидается, это: ABC

В результате для А, В (1) С должно быть АВ (1) С, но то, что я получаю: АВ 1

select REGEXP_SUBSTR('A;B(1);C','[^(";")]+',1,1), 
REGEXP_SUBSTR('A;B(1);C','[^(";")]+',1,2), 
REGEXP_SUBSTR('A;B(1);C','[^(";")]+',1,3) 
from dual; 

это означает, что «(» определяется как разделитель, но я не понимаю, это поведение. Может кто-то пожалуйста просветить меня?

ответ

5

[] - это Multilingual Regular Expression Syntax, в котором указано выражение «Скобка» для указания соответствующего списка, который должен соответствовать любому из выражений, представленных в списке. Nonmatching выражения списка начинается с циркумфлексом (^) и определяет список, который соответствует любому символу, для выражений, представленных в списке, кроме.»

Например

select REGEXP_SUBSTR('"A";"B(1)";"C"','[^";"]+',1,1) 
from dual; 

возвратит A B(1) C где [^";"]+ считает " ИЛИ ; в качестве сепаратора

Аналогично в вашем примере [^(";")]+ считает " ИЛИ ; ИЛИ ( ИЛИ ), как с отпавших против вашего ожидания.

Так что для вашего ожидаемого выхода, вы можете попробовать

select REGEXP_SUBSTR('A;B(1);C','[^;]+',1,1), 
REGEXP_SUBSTR('A;B(1);C','[^;]+',1,2), 
REGEXP_SUBSTR('A;B(1);C','[^;]+',1,3) 
from dual; 
+0

Большое спасибо, я понял. – user1838910

+0

@ user1838910 Вы можете принять это как решение и закрыть этот вопрос, если вы счастливы – SriniV

1

Еще раз я поднимаюсь на моей мыльнице, чтобы предупредить людей об опасности использования регулярных выражений в формате '[^;]+' для разбора строк с разделителями. Покайтесь и спаситесь! Он не обрабатывает элементы NULL и возвращает неожиданные результаты. См. here для получения дополнительной информации и подтверждения. Пожалуйста, используйте этот формат, а и спать спокойно, зная, ваш вывод точен:

Обратите внимание на второй элемент (NULL)

SQL> with tbl(str) as (
     select 'A;;B(1);C' from dual 
    ) 
    select regexp_substr(str, '(.*?)(;|$)', 1, level, NULL, 1) 
    from tbl 
    connect by level <= regexp_count(str, ';') + 1; 

REGEXP_SU 
--------- 
A 

B(1) 
C 

SQL> 

Обратите внимание на NULL возвращается для элемента 2, как и ожидалось. Если вы используете формат регулярных выражений '[^;]+' и попытаться получить 2-го элемента, вы получите 'B(1)' что неверно, так как это третий элемент:

НЕ ИСПОЛЬЗОВАТЬ:

SQL> with tbl(str) as (
    2 select 'A;;B(1);C' from dual 
    3 ) 
    4 select regexp_substr(str, '[^;]+', 1, level) 
    5 from tbl 
    6 connect by level <= regexp_count(str, ';') + 1; 

REGEXP_SU 
--------- 
A 
B(1) 
C 


SQL> 

Посмотрите близко, последний имеет значение NULL. Представьте себе все неправильные отчеты. Не позволяйте одному из них быть вашим!

+0

Я знаю об этом. Замена '|' by '| 'перед использованием regexp_substr выполняет эту работу в моем случае. Тем не менее спасибо за намек. – user1838910

+0

Не уверен, что вы говорите, но realspirituals заслуживает голосования, поскольку его ответ правильный для вашего вопроса. Моя информация - дополнительная информация, о которой нужно знать.Независимо от того, что вы делаете, убедитесь, что вы тестируете все возможные комбинации неожиданных данных, о которых вы можете подумать, и убедитесь, что ваше решение обрабатывает их все! –

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

  • Нет связанных вопросов^_^