Reputation: 83
I have a PS script that checks some custom user's properties in Active Directory. One of the properties is "Manager".
$data = Get-ADUser $user -Properties * | Select-Object DisplayName, LockedOut, Enabled, LastLogonDate, PasswordExpired, EmailAddress, Company, Title, Manager, Office
Write-Host "9." $user "manager is" $data.manager -ForegroundColor Green
When I run the script I've got:
User's manager is CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com
The problem is that text "OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com"
will be different for some users
How can I modify output and remove everything except "cool.boss"
?
Thank you in advance
Upvotes: 4
Views: 20475
Reputation: 437833
To complement the helpful answers here with PowerShell-idiomatic regex solutions, which are not fully robust, however (see below):
-split
, the regex-based string splitting operator:$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
($dn -split '^CN=|,')[1] # -> 'cool.boss'
-replace
, the regex-based string substitution operator:$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'
$dn -replace '^CN=([^,]+).*', '$1' # -> 'cool.boss'
Note:
In principle, DNs (Distinguished Names), of which the input string is an example, can have ,
characters embedded in the values of the name-value pairs that make up a DN, escaped as \,
(or, in hex notation, \2C
); e.g., "CN=boss\, cool,OU=Users,..."
A truly robust implementation needs to take that into account, and would ideally also unescape the resulting value; none of the existing answers do that as of this writing; see below for a solution.
Robustly parsing an LDAP/AD DN (Distinguished Name):
The following Split-DN
function:
,
chars., as well as other escape sequences, correctly\
, but also converting escape sequences in the form \<hh>
, where hh
is a two-digit hex. number representing a character's code point, to the actual character they represent (e.g, \3C
, is converted to a <
character).CN
, OU
), with the values for names that occur multiple times - such as OU
- represented as an array.Example call:
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}
Note how escape sequence \3C
was converted to <
, the character it represents, and how \,
was recognized as an ,
embedded in the CN
value.
Since the input string contained multiple OU
and DC
name-value pairs (so-called RDNs, relative distinguished names), their corresponding hashtable entries became arrays of values (signified in the truncated-for-display-only output with { ... }
, with ,
separating the elements).
Function Split-DN
's source code:
Note: For brevity, error handling and validation are omitted.
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, convert 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
}
Upvotes: 3
Reputation: 17055
This should be a more or less safe and still easy way to parse it:
($data.manager -split "," | ConvertFrom-StringData).CN
Upvotes: 6
Reputation: 4694
You can use the .split()
method to get what you want.
$DN = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"
$DN.Split(',').Split('=')[1]
What i'd recommend, is throwing it into another Get-ADUser
to get the displayname for neater output(:
Upvotes: 2
Reputation: 17007
you could use regex for that:
$s = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"
$pattern = [regex]"CN=.*?OU"
$r = $pattern.Replace($s, "CN=OU")
$r
Upvotes: 1