要使用 PowerShell 惯用的正则表达式解决方案补充此处的有用答案:
$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
($dn -split '(?:^|,)CN=|,')[1] # -> 'cool.boss'
$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
$dn -replace '(?:^|,)CN=([^,]+).*', '$1' # -> 'cool.boss'
笔记:
上述解决方案不依赖于输入中名称-值对 (RDN) 的特定顺序(即CN
条目不必是第一个),但它们确实只提取第一个 CN
条目的值,如果有多个存在,并且他们确实假设(至少)一个存在。
原则上,以输入字符串为例的DN(可分辨名称)可以在构成 DN 的名称-值对的值中嵌入,
字符,转义为(或十六进制表示法);例如,\,
\2C
"CN=boss\, cool,OU=Users,..."
一个真正强大的解决方案必须考虑到这一点,并且理想情况下也不会逃避产生的价值;在撰写本文时,现有的答案都没有这样做;见下文。
稳健地解析 LDAP/AD DN(专有名称):
以下Split-DN
功能:
- 正确处理转义的、嵌入
,
的字符以及其他转义序列
- 取消转义值,这不仅包括删除 syntactic
\
,还包括以 形式转换转义序列\<hh>
,其中hh
是两位数的十六进制。表示字符代码点的数字,到它们所表示的实际字符(例如,\3C
转换为<
字符)。
- 输出一个有序的哈希表,其键是名称组件(例如,,
CN
) ,名称多次OU
出现的值- 例如- 表示为数组。OU
示例调用:
PS> Split-DN 'CN=I \3C3 Huckabees\, I do,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
Name Value
---- -----
CN I <3 Huckabees, I do
OU {Users, SO, PL, RET…}
DC {domain, com}
请注意转义序列\3C
是如何转换为<
、它所代表的字符以及如何\,
被识别为,
嵌入在CN
值中的。
由于输入字符串包含多个 OU
名称-DC
值对(所谓的 RDN,相对专有名称),它们对应的哈希表条目变成了值数组(在仅显示截断的输出中用 表示{ ... }
,并,
分隔元素)。
函数Split-DN
的源代码:
注意:为简洁起见,省略了错误处理和验证。
function Split-DN {
param(
[Parameter(Mandatory)]
[string] $DN
)
# Initialize the (ordered) output hashtable.
$oht = [ordered] @{}
# Split into name-value pairs, while correctly recognizing escaped, embedded
# commas.
$nameValuePairs = $DN -split '(?<=(?:^|[^\\])(?:\\\\)*),'
$nameValuePairs.ForEach({
# Split into name and value.
# Note: Names aren't permitted to contain escaped chars.
$name, $value = ($_ -split '=', 2).Trim()
# Unescape the value, if necessary.
if ($value -and $value.Contains('\')) {
$value = [regex]::Replace($value, '(?i)\\(?:[0-9a-f]){2}|\\.', {
$char = $args[0].ToString().Substring(1)
if ($char.Length -eq 1) { # A \<literal-char> sequence.
$char # Output the character itself, without the preceding "\"
}
else { # A \<hh> escape sequence, conver the hex. code point to a char.
[char] [uint16]::Parse($char, 'AllowHexSpecifier')
}
})
}
# Add an entry to the output hashtable. If one already exists for the name,
# convert the existing value to an array, if necessary, and append the new value.
if ($existingEntry = $oht[$name]) {
$oht[$name] = ([array] $existingEntry) + $value
}
else {
$oht[$name] = $value
}
})
# Output the hashtable.
$oht
}