匹配正则表达式并用特殊字符替换错误
match regex and replace bug with special charakters
我已经构建了一个脚本来读取所有 Active Directory 组成员身份并将它们保存到一个文件中。
问题是,Get-ADPrincipalGroupMembership
cmdlet 会像这样输出所有组:
CN=Group_Name,OU=Example Mail,OU=Example Management, DC=domain,DC=de
所以我需要在这里做一些正则表达式 and/or 替换魔术,只用从 "CN=" 开始到第一个 ",".[=15 的第一个字符串替换整行=]
结果是这样的:
Group_Name
所以,有一个广告组不会被替换。我已经知道为什么了,但我不知道如何解决这个问题。在我们的 AD 中有一个具有特殊字符的组,如下所示:
CN=AD_Group_Name+up,OU=Example Mail,OU=Example Management, DC=domain,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
}
}
您的群组名称包含一个字符 (+
),该字符在正则表达式中具有特殊含义(前一个表达式的一次或多次)。要禁用特殊字符,请在替换操作中转义搜索字符串:
... -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
cmdlet 扩展组成员的名称:
Get-ADPrincipalGroupMembership $UserName |
Get-ADObject |
Select-Object -Expand Name
Ansgar 的答案在使用正则表达式方面要好得多,但我相信在这种情况下,您可以使用 IndexOf 函数做一个肮脏的解决方法。在您的 if 语句中,您可以执行以下操作:
if ($line -like "CN=*") {
$ADGroup = $line.Substring(3, $line.IndexOf(',')-3)
}
这里起作用的原因是您知道输出将以 CN=YourGroupName 开头,这意味着您知道所需的字符串从第 4 个字符开始。其次,您知道组名称不包含任何逗号,这意味着 IndexOf(',') 将始终找到该字符串的末尾,因此您无需担心 nth occurrence of a string in a string.
首先,这可能是个好主意,也可能不是个好主意,这取决于你在这里做什么。 CN 是 /not/ 不可变的,因此如果您将它作为密钥存储在某处,您很可能会 运行 遇到问题。不过,组的 objectGUID
属性 是一个很好的主键。
就获取此值而言,我认为您可以大大简化它。该 cmdlet 输出的 name
属性 将始终具有您想要的值:
Get-ADPrincipalGroupMembership <username> | select name
我已经构建了一个脚本来读取所有 Active Directory 组成员身份并将它们保存到一个文件中。
问题是,Get-ADPrincipalGroupMembership
cmdlet 会像这样输出所有组:
CN=Group_Name,OU=Example Mail,OU=Example Management, DC=domain,DC=de
所以我需要在这里做一些正则表达式 and/or 替换魔术,只用从 "CN=" 开始到第一个 ",".[=15 的第一个字符串替换整行=]
结果是这样的:
Group_Name
所以,有一个广告组不会被替换。我已经知道为什么了,但我不知道如何解决这个问题。在我们的 AD 中有一个具有特殊字符的组,如下所示:
CN=AD_Group_Name+up,OU=Example Mail,OU=Example Management, DC=domain,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
}
}
您的群组名称包含一个字符 (+
),该字符在正则表达式中具有特殊含义(前一个表达式的一次或多次)。要禁用特殊字符,请在替换操作中转义搜索字符串:
... -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
cmdlet 扩展组成员的名称:
Get-ADPrincipalGroupMembership $UserName |
Get-ADObject |
Select-Object -Expand Name
Ansgar 的答案在使用正则表达式方面要好得多,但我相信在这种情况下,您可以使用 IndexOf 函数做一个肮脏的解决方法。在您的 if 语句中,您可以执行以下操作:
if ($line -like "CN=*") {
$ADGroup = $line.Substring(3, $line.IndexOf(',')-3)
}
这里起作用的原因是您知道输出将以 CN=YourGroupName 开头,这意味着您知道所需的字符串从第 4 个字符开始。其次,您知道组名称不包含任何逗号,这意味着 IndexOf(',') 将始终找到该字符串的末尾,因此您无需担心 nth occurrence of a string in a string.
首先,这可能是个好主意,也可能不是个好主意,这取决于你在这里做什么。 CN 是 /not/ 不可变的,因此如果您将它作为密钥存储在某处,您很可能会 运行 遇到问题。不过,组的 objectGUID
属性 是一个很好的主键。
就获取此值而言,我认为您可以大大简化它。该 cmdlet 输出的 name
属性 将始终具有您想要的值:
Get-ADPrincipalGroupMembership <username> | select name