Rakha
Rakha

Reputation: 2064

Optimal way of working with a regular expression

I am trying to isolate just the name of a group.

Doing this command:

Get-ADUser aaa00 -Properties memberof |
    Select-Object -ExpandProperty memberof 

returns:

CN=GroupName,OU=xxx,OU=xxx,DC=xxx,DC=xxx,DC=xxx

I want only what is after CN=, which is the group name.

So I'm doing:

Get-ADUser aaa00 -Properties memberof |
    Select-Object -ExpandProperty memberof |
    ForEach-Object { 
        $isolateName = $_ -match "(?<=\=)(.*?)(?=\,)"
        $matches[0]
    }

which works and returns only the group name.

However, I want to store the group names in an array for later use, so I'm doing:

Get-ADUser aaa00 -Properties memberof |
    Select-Object -ExpandProperty memberof |
    ForEach-Object { 
        $isolateName = $_ -match "(?<=\=)(.*?)(?=\,)"
        [array]$Names += $matches[0]
    }

This works fine.

My question is, is that the optimal way to work with RegEx?

I do the -match then check $matches but couldn't I just do it inverted and do "replace all that is NOT what is matched by my regex by nothing".

How do I do that, basically negate that whole Regex?

P.S.: I know I can use Get-ADPrincipalGroupMembership to get the name only but I'm not using that command since it is incredibly slow compared to Get-ADUser.

Upvotes: 2

Views: 531

Answers (1)

mklement0
mklement0

Reputation: 439287

Try the following, which uses the -replace operator to extract the group names:

$groupNames = Get-AdUser gar25 -properties memberof | 
  Select-Object -ExpandProperty memberof |
    ForEach-Object { $_ -replace '^CN=(.+?),.*', '$1' }

Note: Assumes that group names contain no escaped , chars. (\,).

  • The array of group names is implicitly created simply by assigning the entire pipeline to variable $groupNames. (If there's a chance that only 1 group may be returned and you want to make sure that the result is an array, enclose the entire pipeline in @(...), the array-subexpression operator.

  • $_ -replace '^CN=(.+?),.*', '$1' extracts the group name from each input:

    • ^CN= matches literal CN= at the start (^) of the input string.
    • (.+?) non-greedily (?) matches a nonempty run of arbitrary characters (.+), and uses a capture group ((...)) to capture that run.
    • ,.* matches a literal , followed by a (greedily matched) potentially empty run of arbitrary characters (.*), i.e., it matches the remaining input.
    • Since the capture group matches non-greedily, it captures everything up to the first , char, which is assumed to be the group name.
    • Overall, the regex by design matches the entire input string, so that by only using $1- what the 1st capture group captured - as the replacement operand it is just the group name that is returned.

Upvotes: 3

Related Questions