У меня недавно была потребность в этом, поэтому я создал тот, который полностью соответствует синтаксису отличительного имени LDAPv3 на RFC-2253 .
Тип атрибута
attributeType может быть выражен двумя способами. Буквенно-цифровая строка, которая начинается с буквы, проверяется с помощью:
[A-Za-z][\w-]*
Или это может быть OID, проверенный с помощью:
\d+(?:\.\d+)*
Итак, attributeType проверяется с использованием:
[A-Za-z][\w-]*|\d+(?:\.\d+)*
Значение атрибута
Значение атрибута может быть выражено тремя способами. Шестнадцатеричная строка, представляющая собой последовательность шестнадцатеричных пар с ведущим #
. Шестнадцатеричная строка проверяется с использованием:
#(?:[\dA-Fa-f]{2})+
Или сбежавшая строка; каждый не специальный символ выражается «как есть» (проверяется с использованием [^,=\+<>#;\\"]
). Специальные символы могут быть указаны с начальным \
(проверяется с помощью \\[,=\+<>#;\\"]
). Наконец, любой символ может быть выражен в виде шестнадцатеричной пары с ведущим \
(проверяется с использованием \\[\dA-Fa-f]{2}
). Экранированная строка проверяется с использованием:
(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*
Или строка в кавычках; значение начинается и заканчивается "
и может содержать любой символ без экранирования, кроме \
и "
. Кроме того, можно использовать любой из приведенных выше экранированных строк. Строка в кавычках проверяется с использованием:
"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"
Все вместе, attributeValue проверяется с использованием:
#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"
Наименование компонента
Компонент имени в BNF:
name-component = attributeTypeAndValue *("+" attributeTypeAndValue)
attributeTypeAndValue = attributeType "=" attributeValue
В RegEx есть:
(?#attributeType)=(?#attributeValue)(?:\+(?#attributeType)=(?#attributeValue))*
Замена заполнителей (?#attributeType)
и (?#attributeValue)
вышеуказанными значениями дает нам:
(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*
Который проверяет один компонент имени.
Отличительное имя
Наконец, BNF для выдающегося имени:
name-component *("," name-component)
В RegEx есть:
(?#name-component)(?:,(?#name-component))*
Замена заполнителя (? # Name-component) на указанное выше значение дает нам:
^(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*(?:,(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*)*$
Проверьте это здесь