Как разделить различаемое имя?

#powershell #ou #distinguishedname

Вопрос:

У меня есть список людей и их имена из объявления (у меня нет прямого доступа к этому объявлению). Их DNS находятся в формате:

 $DNList = 'CN=Bob Dylan,OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com',
          'CN=Ray Charles,OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com',
          'CN=Martin Sheen,OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com'
 

Я хотел бы $DNList вернуть следующее:

 OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com
 

Комментарии:

1. Здесь уже есть много хороших ответов. Я просто хочу отметить, что «поля» в DN сами могут содержать запятую, и когда они это делают, они экранируются обратной косой чертой, чтобы вы могли иметь CN=Dylan, Bob,OU=Users . Просто будьте осторожны, какой бы метод вы ни выбрали, он справится с этим.

Ответ №1:

Я решил превратить свой комментарий в ответ:

 $DNList | ForEach-Object {
    $_ -replace '^. ?(?<!\),',''
}
 

Визуализация регулярных выражений

Демонстрация Debuggex

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

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

Комментарии:

1. Вот дерьмо, это правда, не так ли.

2. Моя работа использует Last, First отображаемые имена в рекламе, поэтому я вижу это все время 🙂

3. Попытался подкрепить свой ответ этим фактом.

4. Я согласился с этим ответом, и полученные данные выглядят хорошо, по крайней мере, при случайной выборочной проверке. Однако это было странно… на фоне списка из 1600 ненужных предметов, первой дюжины или около того, казалось, что весь процесс истек по времени и/или застрял. Но подождал около 20 секунд и быструю вспышку с правильными результатами. Как ни странно, это выглядело, но работало чисто и ясно. Спасибо вам очень, очень большое!

Ответ №2:

Вы можете удалить первый элемент с помощью такой замены:

 $DNList -replace '^.*?,(..=.*)

 ^.*?,   является кратчайшим совпадением от начала строки до запятой.
 (..=.*)$   соответствует остальной части строки (начиная с двух символов после запятой, за которыми следует  =  символ) и группирует их, чтобы на совпадение можно было ссылаться при замене как  $1  .


Комментарии:

1. Приятно - я думаю, что разделение/объединение может быть более читабельным, если вы менее знакомы с powershell (или регулярными выражениями), но является ли регулярное выражение быстрее? (не имело бы значения для этого примера, но подумайте о том, где есть больше предметов для работы, чем 3 здесь)

2. @GrahamGold Примерно в 10 раз быстрее, согласно быстрому тесту, который я только что провел на более крупной выборке (1300 элементов). Кроме того, простое разделение DNs может вызвать проблемы, когда первый элемент содержит запятую.

3. У меня было предчувствие, что это может быть :-) Спасибо, что проверили это

Ответ №3:

У вас есть 7 элементов на пользователя, разделенных запятыми, и вы хотите избавиться от первого.

Итак, разделите каждый элемент в массиве, используя запятые в качестве разделителя, верните совпадения 1-6 (0-первый элемент, который вы хотите пропустить), затем снова соедините запятыми, например

 $DNList = $DNList|foreach{($_ -split ',')[1..6] -join ','}
 

Если вы затем войдете $DNList , он вернется

 OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com
 

Комментарии:

1. Когда я пытаюсь это сделать, я получаю результат,который не соответствует тому, что ищет операция :- OU=Пользователи, CN=Боб Дилан,DC=com, OU=Подрядчики,CN=Рэй Чарльз,DC=com, OU=Пользователи,CN=Мартин Шин,DC=com

2. Вы правы. То, что я имел в виду, предназначалось для другого сценария. Пожалуйста, не обращайте внимания на это предложение. Предложение @Matt - лучший способ обработки переменной длины.

Ответ №4:

Аналогично ответу Грэхема, но удалены жестко закодированные значения массива, поэтому он просто удалит часть CN, не беспокоясь о том, как долго DN.

 $DNList | ForEach-Object{($_ -split "," | Select-Object -Skip 1) -join ","}
 

У Ансгара, скорее всего, есть веская причина, но вы можете просто использовать регулярное выражение, чтобы удалить все до первой запятой

 $DNList -replace "^.*?,"
 

Обновление на основе briantist

Чтобы сохранить другой ответ, но тот, который работает, это регулярное выражение все еще может иметь проблемы, но я сомневаюсь, что эти символы будут отображаться в имени пользователя

 $DNList -replace "^.*?,(?=OU=)"
 

Регулярное выражение использует взгляд вперед , чтобы убедиться, что за, следует OU=

Точно так же вы могли бы сделать это

 ($DNList | ForEach-Object{($_ -split "(,OU=)" | Select-Object -Skip 1) -join ""}) -replace "^,"
 

Комментарии:

1. С помощью powershell существует более одного способа достижения одной и той же цели - ответы на этот вопрос являются убедительными 🙂 Почему я люблю (а иногда и ненавижу) powershell!

2. @GrahamGold очень верно. Это то, как я изучаю другие подходы. Видеть, что делают другие люди.

, '$1'
^.*?, является кратчайшим совпадением от начала строки до запятой.
(..=.*)$ соответствует остальной части строки (начиная с двух символов после запятой, за которыми следует = символ) и группирует их, чтобы на совпадение можно было ссылаться при замене как $1 .

Комментарии:

1. Приятно — я думаю, что разделение/объединение может быть более читабельным, если вы менее знакомы с powershell (или регулярными выражениями), но является ли регулярное выражение быстрее? (не имело бы значения для этого примера, но подумайте о том, где есть больше предметов для работы, чем 3 здесь)

2. @GrahamGold Примерно в 10 раз быстрее, согласно быстрому тесту, который я только что провел на более крупной выборке (1300 элементов). Кроме того, простое разделение DNs может вызвать проблемы, когда первый элемент содержит запятую.

3. У меня было предчувствие, что это может быть 🙂 Спасибо, что проверили это

Ответ №3:

У вас есть 7 элементов на пользователя, разделенных запятыми, и вы хотите избавиться от первого.

Итак, разделите каждый элемент в массиве, используя запятые в качестве разделителя, верните совпадения 1-6 (0-первый элемент, который вы хотите пропустить), затем снова соедините запятыми, например


Если вы затем войдете $DNList , он вернется


Комментарии:

1. Когда я пытаюсь это сделать, я получаю результат,который не соответствует тому, что ищет операция :- OU=Пользователи, CN=Боб Дилан,DC=com, OU=Подрядчики,CN=Рэй Чарльз,DC=com, OU=Пользователи,CN=Мартин Шин,DC=com

2. Вы правы. То, что я имел в виду, предназначалось для другого сценария. Пожалуйста, не обращайте внимания на это предложение. Предложение @Matt — лучший способ обработки переменной длины.

Ответ №4:

Аналогично ответу Грэхема, но удалены жестко закодированные значения массива, поэтому он просто удалит часть CN, не беспокоясь о том, как долго DN.


У Ансгара, скорее всего, есть веская причина, но вы можете просто использовать регулярное выражение, чтобы удалить все до первой запятой


Обновление на основе briantist

Чтобы сохранить другой ответ, но тот, который работает, это регулярное выражение все еще может иметь проблемы, но я сомневаюсь, что эти символы будут отображаться в имени пользователя


Регулярное выражение использует взгляд вперед , чтобы убедиться, что за, следует OU=

Точно так же вы могли бы сделать это


Комментарии:

1. С помощью powershell существует более одного способа достижения одной и той же цели — ответы на этот вопрос являются убедительными 🙂 Почему я люблю (а иногда и ненавижу) powershell!

2. @GrahamGold очень верно. Это то, как я изучаю другие подходы. Видеть, что делают другие люди.