Oracle 11g - REGEXP_REPLACE - Subexpressions/ различные совпадения

SQLFiddle: http://sqlfiddle.com/

Я работаю над запросом, который возвращает DN объекта:(cn=name,ou=folder,dc=hostname,dc=com)

Моя цель - вернуть эту информацию в более "симпатичном" виде, похожем на AD:(name\folder\hostname.com)

Я сделал это неуклюже:

REGEXP_REPLACE(REGEXP_REPLACE(TEST, '.*CN=(.+?),DC=.*', '\1', 1, 1, 'i'), ',OU=', '\', 1, 0, 'i') -- grab everything between CN= and DC=, replace with \'s --
|| '\' || 
REGEXP_REPLACE(SUBSTR(TEST, REGEXP_INSTR(TEST, ',DC=', 1, 1, 0, 'i')+4),',DC=','.', 1, 0, 'i') -- grab everything after DC=, replace with .'s --

Хотя это работает, я не в восторге от того, насколько это слишком сложно (и что это связано с необходимостью сшивать две строки regex'd).

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

REGEXP_REPLACE(test, '(,?(cn=|ou=)(.+?),)', '\3\')

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

Пример ввода (может иметь несколько OU /DC):

cn=name,ou=subgroup,ou=group,dc=accounts,dc=hostname,dc=com cn=name,ou=group,dc=hostname,dc=com

Ожидаемый результат

name\subgroup\group\accounts.hostname.com name\group\hostname.com

Входящие данные являются динамическими и никогда не устанавливают количество OU или DC.

2 ответа

Решение

Вы можете использовать

SELECT REPLACE(
    REGEXP_REPLACE(
        test, 
        '(^|,)(cn|ou)=([^,]*)(,dc=)?', 
        '\3\\'), 
    ',dc=', 
    '.') 
FROM regexTest

Смотрите SQLFiddle.

Первый (^|,)(cn|ou)=([^,]*)(,dc=)? регулярные выражения , или начало строки, затем cn или же ou, затем =, затем записывает в группу 3 ноль или более символов, отличных от запятой, а затем сопоставляет необязательный ,dc= подстрока (таким образом, удаляя первый экземпляр ,dc=). Заменой является содержимое группы 3 и обратный слеш.

Итак, вторая операция проста, просто замените все ,dc= с ., вам даже не нужно регулярное выражение для этого.

Может быть что-то вроде этого:

SELECT nvl(regexp_replace(
    regexp_replace(
      nullif(
        regexp_replace(test, '^cn=(.+?),DC=(.+?)$', '\1 \2',1,1,'i') 
        , test
      ) , ' |,(CN|OU)=', '\\', 1, 0,'i'
    ), ',DC=', '.', 1, 0,'i'
    ),test) result
FROM regexTest

Этот запрос не меняет входные данные, если нет DC=,

Другие вопросы по тегам