Regex в Postgres для извлечения полного DN в OpenLDAP - PullRequest
0 голосов
/ 04 июля 2018

У меня есть программа для передачи полной строки групп пользователя в OpenLDAP на Postgres запрос. Строка в точности такая:

( 'cn=user1,ou=org1,ou=suborg1,o=myorg','cn=user2,ou=org2,ou=suborg1,o=myorg','cn=user3,ou=org1,ou=suborg1,o=myorg','cn=user4,ou=org1,ou=suborg2,o=myorg' )

В запросе я хочу, чтобы это было только в Postgres :

'user1','user3'

В основном извлекаем значение cn=, когда остальная часть строки равна ou=org1,ou=suborg1,o=myorg.

user2 имеет ou=org2,ou=suborg1,o=myorg, то есть org2, поэтому он не будет совпадать. user4 не будет совпадать с suborg2, ... Вариант не ограничен, поэтому мне нравится искать только точное совпадение ou=org1,ou=suborg1,o=myorg.

Я знаю, как это сделать replace, но он не может справиться с неограниченными сценариями. Есть ли чистый способ сделать это в regexp_replace или regexp_extract?

Ответы [ 3 ]

0 голосов
/ 07 июля 2018

Вероятно, самым чистым является использование SUBSTRING, которое может вернуть только захваченную подстроку:

SELECT SUBSTRING(strs FROM 'cn=([^,]+),ou=org1,ou=suborg1,o=myorg') FROM tb1;

Здесь вы сопоставляете cn=, затем записываете в Группу 1 любой один или несколько символов, отличных от , с выражением в отрицательной скобке [^,]+, а затем сопоставляете ,ou=org1,ou=suborg1,o=myorg, чтобы убедиться, что есть требуемая правая рука контекст.

Иначе, вы можете попробовать подход REGEXP_REPLACE, но при этом значения, в которых не найдено совпадений, останутся без изменений:

SELECT REGEXP_REPLACE(strs, '.*cn=([^,]+),ou=org1,ou=suborg1,o=myorg.*', '\1') from tb1;

Соответствует любым 0+ символам с .*, затем cn=, снова захватывает символы без запятой в Группу 1 и затем сопоставляет ,ou=org1,ou=suborg1,o=myorg и 0+ символов до конца строки.

См. онлайн-демонстрацию PostgreSQL :

CREATE TABLE tb1
    (strs character varying)
;

INSERT INTO tb1
    (strs)
VALUES
    ('cn=user1,ou=org1,ou=suborg1,o=myorg'),
    ('cn=user2,ou=org2,ou=suborg1,o=myorg'),
    ('cn=user3,ou=org1,ou=suborg1,o=myorg'),
    ('cn=user4,ou=org1,ou=suborg2,o=myorg')
;

SELECT REGEXP_REPLACE(strs, '.*cn=([^,]+),ou=org1,ou=suborg1,o=myorg.*', '\1') from tb1;
SELECT substring(strs from 'cn=([^,]+),ou=org1,ou=suborg1,o=myorg') from tb1;

Результаты:

enter image description here

Обратите внимание, что вы можете использовать очень полезную границу слова \y (см. Таблица 9.20. Побег ограничения регулярного выражения ), если вы не хотите совпадение ocn= с cn=,

'.*\ycn=([^,]+),ou=org1,ou=suborg1,o=myorg\y.*'
   ^^                                     ^^
0 голосов
/ 08 июля 2018

Вы можете использовать regexp_matches(), чтобы получить все соответствующие cn . Затем используйте string_agg(), чтобы составить их список через запятую.

SELECT string_agg(ldap.cn[1],
                  ',') cn
       FROM regexp_matches('( ''cn=user1,ou=org1,ou=suborg1,o=myorg'',''cn=user2,ou=org2,ou=suborg1,o=myorg'',''cn=user3,ou=org1,ou=suborg1,o=myorg'',''cn=user4,ou=org1,ou=suborg2,o=myorg'' )',
                           '''cn=([^,]*),ou=org1,ou=suborg1,o=myorg''',
                           'g') ldap(cn);

SQL Fiddle

0 голосов
/ 05 июля 2018

Попробуйте регулярное выражение: (?<=cn=)\w+(?=,ou=org1,ou=suborg1,o=myorg)

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...