Сопоставьте регулярное выражение и замените ошибку специальными характеристиками

Я создал скрипт для чтения всех членств в группах Active Directory и сохранения их в файл. Проблема в том, Get-ADPrincipalGroupMembership Командлет выводит все группы следующим образом:

CN = Group_Name,OU= Пример почты,OU= Пример управления, DC= домен,DC=de

Так что мне нужно сделать немного магии регулярных выражений и / или замены, чтобы заменить всю строку только первой строкой, начинающейся с "CN=" до первой ",".

Результат будет таким:

Имя группы

Итак, есть одна группа AD, которая не будет заменена. Я уже понял, почему, но я не знаю, как обойти это. В нашей AD есть группа со специальным символом, что-то вроде этого:

CN = AD_Group_Name + up,OU= Пример почты,OU= Пример управления, DC= домен,DC=de

Таким образом, из-за маленького знака "+" вся линия даже не трогается.

Кто-нибудь знает, почему это происходит?

Import-Module ActiveDirectory

# Get Username
Write-Host "Please enter the Username you want to export the AD-Groups from."
$UserName = Read-Host "Username"

# Set Working-Dir and Output-File Block:
$WorkingDir = "C:\Users\USER\Desktop"
Write-Host "Working directory is set to " + $WorkingDir
$OutputFile = $WorkingDir + "\" + $UserName + ".txt"

# Save Results to File
Get-ADPrincipalGroupMembership $UserName |
    select -Property distinguishedName |
    Out-File $OutputFile -Encoding UTF8

# RegEx-Block to find every AD-Group in Raw Output File and delete all
# unnaccessary information:
[regex]$RegEx_mark_whole_Line = "^.*"
# The ^ matches the start of a line (in Ruby) and .* will match zero or more
# characters other than a newline
[regex]$RegEx_mark_ADGroup_Name = "(?<=CN=).*?(?=,)"
# This regex matches everything behind the first "CN=" in line and stops at
# the first "," in the line. Then it should jump to the next line.

# Replace-Block (line by line): Replace whole line with just the AD group
# name (distinguishedName) of this line.
foreach ($line in Get-Content $OutputFile) {
    if ($line -like "CN=*") {
        $separator = "CN=",","
        $option = [System.StringSplitOptions]::RemoveEmptyEntries
        $ADGroup = $line.Split($separator, $option)
        (Get-Content $OutputFile) -replace $line, $ADGroup[0] |
            Set-Content $OutputFile -Encoding UTF8
    }
}

3 ответа

Решение

Во-первых, в зависимости от того, что вы делаете здесь, это может быть или не быть хорошей идеей. CN является / не / неизменным, поэтому, если вы храните его где-то в качестве ключа, вы, вероятно, столкнетесь с проблемами в будущем. objectGUID свойство группы является хорошим первичным ключом.

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

Get-ADPrincipalGroupMembership <username> | select name

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

... -replace [regex]::Escape($line), $ADGroup[0]

Тем не менее, я не вижу, для чего вам нужна эта замена. По сути, вы заменяете строку в выходном файле подстрокой из той строки, которую вы уже извлекли ранее. Просто запишите эту подстроку в выходной файл, и все готово.

$separator = 'CN=', ','
$option    = [StringSplitOptions]::RemoveEmptyEntries
(Get-Content $OutputFile) | ForEach-Object {
    $_.Split($separator, $option)[0]
} | Set-Content $OutputFile

Еще лучше использовать Get-ADObject Командлет для расширения имен членов группы:

Get-ADPrincipalGroupMembership $UserName |
    Get-ADObject |
    Select-Object -Expand Name

Ответ Ансгара намного лучше с точки зрения использования регулярных выражений, но я считаю, что в этом случае вы могли бы сделать грязный обходной путь с функцией IndexOf. В своем условии if вы можете сделать следующее:

if ($line -like "CN=*") {
    $ADGroup = $line.Substring(3, $line.IndexOf(',')-3)
    }

Причина, по которой это работает, заключается в том, что вы знаете, что вывод будет начинаться с CN=YourGroupName, что означает, что вы знаете, что строка, которую вы хотите, начинается с 4-го символа. Во-вторых, вы знаете, что имя группы не будет содержать запятой, то есть IndexOf(',') всегда будет находить конец этой строки, поэтому вам не нужно беспокоиться о n-м появлении строки в строке.

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