Get-ADUser -Filter Variable

Friends, I am trying to find records in Active Directory by appending the input last name, (SN) with one or two numbers.
Here’s an example.
If the input is Jones, I want to match on all that exactly equal to any of these:
Jones1
Jones99
Jones1abc
Jones99abcdefg
Jones123456

This is the snippet I came up with but it will not find an Active Directory Record that I know is there, the SN = Wiggins2

$Input = "Wiggins"

# Define the filter variable 
$NewVariable =  '$Input[0-9][0-9]*'
$filterCondition = "(SN -eq '$NewVariable')" 
# Execute Get-ADUser with the filter
$MatchingUsers = Get-ADUser -Filter $filterCondition | Select-Object SamAccountName, GivenName, SN, Name

# Display the results
if ($MatchingUsers) {
    Write-Host "Matching user accounts found:"
    $MatchingUsers
} else {
    Write-Host "No matching user accounts found."
} 

After running this, $filterCondition has a value of: (SN -eq ‘$Newlast[0-9][0-9]*’)
Thank you in advance for your help on this.

$Input is a reserved variable, see here:

What if you try:

$User = "Wiggins"
$filterCondition = "(SN -like '$User')"


1 Like

$input won’t be translated to the value when using single quotes. You have to use double quotes, as they ‘expandable’. See: about Quoting Rules - PowerShell | Microsoft Learn

I’d suggest a different approach nontheless.

$MatchingUsers = Get-ADUser -Filter  "Surname -like 'Wiggins*'" | Select-Object SamAccountName, GivenName, SN, Name

That should work, but as with anything, test. That says gimme everything like Wiggins* and the * is the wildcard, so that should essentially cover what you’re asking. Obviously it’s an example, so you’ll need to replace Wiggins with a var etc. etc.

tonyd, Yes, indeed, I changed the name of the variable to $User.
And thank you for your suggestion: $filterCondition = “(SN -like ‘$User’)”
I tried that, and it found all the records where Surname = Wiggins, but it did not find that one record where SurName = Wiggins2.

dotnVo, thank you for your reply, I slightly altered your suggestion because the input must be a variable because I will be searching for different names. This is what I tried:

$MatchingUsers = Get-ADUser -Filter  "Surname -like '$User*'" | Select-Object SamAccountName, GivenName, Surname, Name 

After running that, All the records in Active Directory where Surname begin with Wiggins were shown on the console. One of these is Wiggins2. That is good.
But if there were some records with SurName = Wigginsworth, it would show those too. I would not want Wigginsworth, I want it to show only Wiggins or Wiggins1 or Wiggins99… etc.
Another example, if the $input were Jones this code would get Jonesburrow too. I want it to find only Jones or Jones1 or Jones99… etc.

Filter them out (or include only the stuff you want) afterwards by taking the variable and using Where-Object and a -Match operator which uses regex. see: about Comparison Operators - PowerShell | Microsoft Learn

Only certain operators are supported in the filter statement, but there’s nothing wrong with breaking it up into two steps so you can use -match (regex) to filter out (or include only) stuff that you need in a where-object statement. Regex is typically the way to go if you want really specific things. In that case, you can just include stuff that matches the exact pattern you want. Use regex101.com for help on building your regex as you can easily test

dotnVo, Thank you for your reply. I will filter them out as you say. I will also read about Comparison Operators as you suggest. I must also read from regex101.com as you say. By the way, here’s some code I tried with some regex in it. It did not work for me.

$User = "Wiggins"

# Define the filter variable 
$NewVariable =  '$User[0-9][0-9]*'
$filterCondition = "(Surname -eq '$NewVariable')

-eq is looking for an exact match.

As DotNVo said, there is nothing wrong with double filtering and using Regex with -Match. I have no way of testing this with your exact output… but might be worth a shot. I am also horrible with Regex :frowning:

$MatchingUsers = Get-AdUser -Filter "(SN -like '$User*')" | Where-Object {$_.SurName -Match '.+?(?=[0-9])'} | Select-Object SamAccountName, GivenName, SurName, Name
1 Like

That’s not regex though - you’re using -eq. the [0-9] in your context is nothing more than a character in your string. when used at the end of an array (`$Users[0-9], that would return items 1-10 in your $users array.

I don’t want to go too deep into regex for several reasons but once you know exactly what you do and don’t want, you canbuild your regex. Also note that can combined operators so it’s pretty flexible. I’m still kind of confused on which cases you don’t because your initial example shows Jones1abc as something you do want, so maybe only char about characters if they are after a number. in any case… just as an example, let’s say I provide an input of ‘Test’ and I want to check if a surname is equal to that, or is that plus any number of additional digits. In PS that might look something like this:

$MatchingUsers = Get-ADUser -Filter 'SN -like "Test*"'
$UsersICareAbout = $MatchingUsers | Where-Object {$_.Surname -match '^Test\d*$'}

Slight modification to the above code i didn’t need the additional complexity for the example, so I removed it, but was trying to highlight how you can combine operators for more granular returns.

For simplicity sake i’m just hard coding the value, but you can use double quotes and expandalbe strings as well , should work the same, so you can reference vars.

UsersICareAbout (i know i’m super creative :slight_smile: ), would then only include if the surname of the user is test, OR if the surname matches that pattern i provided. To break down the regex:

^ = Start of line
Test = Literal string match, so if the first four characters are not ‘test’ it won’t match. PS is generally case Insensitive, so keep that in mind, as most regex will say its case sensitive, but its actually not in PS. If you wanted it to be though, you can do a -cmatch instead, which makes it case sensitive.
\d* = any digit, any number of times (the quantifer is the asterick)
$ = end of line.

This would return if a surname is Test , or Test1 or Test123456 but it would not return if was TestA123

You might have to build multiple regex or combine etc. but hopefully this helps you better understand how you can use these things together to help accomplish your task.

1 Like

tonyd, thank you for your reply. - I tried your line of code and it found my man, where Surname = Wiggins2. Omigosh! It is a miracle! It did not show any other users, which is what I am looking for. I am going to study your Regex, .+?(?=[0-9]) I can stress test it and improvise the Regex.
Later, I know I can change the Regex to include where Surname = Wiggins too.
For me, the main thing is the arrangement of the Get-AdUser and the -Filter and the Where-Object while using Regex.
I was hoping I would not have to use a Where-Object because I read that it is slower, but even when using Jones as the input , it only took about two seconds. So I am happy with that.
I suppose I should tell you the reason for all this. We often have people with the same first and last names. So they will sometimes tack on a number to the end of their last name and SamAccountName to distinguish one from the other. I think we have nearly twenty people in AD with the name, Joseph Jones!
Thank you for your efforts.

dotnVo, Thank you for your reply. It is the end of the day. I will have to study your reply tomorrow. Not Regex, you say?!? Thank you, I have more jewels to learn, then.

just do the output of your code and see what it’s doing, then go look at the docs for comparison operators: about Operators - PowerShell | Microsoft Learn

Use comparison operators (-eq , -ne , -gt , -lt , -le , -ge ) to compare values and test conditions. For example, you can compare two string values to determine whether they’re equal.
The comparison operators also include operators that find or replace patterns in text. The (-match , -notmatch , -replace ) operators use regular expressions, and (-like , -notlike ) use wildcards * .

So you have a string… you use -eq… it says ‘is this equal to that’? Gotta use the proper operator for the task at hand :slight_smile:

You can practice with regex in PS really easily as well

"string" -Match 'STR'

will return true, because match is not case sensitive, and indeed ‘STR’ are in that string.

same thing with

"string" -Match '^STR'

now add the $ at the end, and it should be false:

"string" -Match '^STR$'

This is because “String” doesn’t do STR then end of line, it has NG in between then ends of line. Just play around with it a bunch and i’m confident you’ll get the hang of it.

1 Like

Thanks very much for your help, fellows, I really appreciate it. I have been refining the REGEX, I am glad to show it to you because it works so well… But I cannot take credit for it.
And right now, this seems to be line I will use in my real script:

$MatchingUsers = Get-AdUser -Filter "(Surname -like '$User*')" | Where-Object {$_.SurName -Match "^$([regex]::Escape($InputUser))(?:\d{1,2}.*)?$"} | Select-Object SamAccountName, GivenName, SurName, Name

And here is the way I tested and developed the REGEX:

# Set the value of $InputUser (change it as needed)
$InputUser = "Smit"

# Sample data for SurName (you can replace this with your actual data)
$Users = @(
    [PSCustomObject]@{ SurName = "Smit" },
    [PSCustomObject]@{ SurName = "Smit1" },
    [PSCustomObject]@{ SurName = "Smit11" },
    [PSCustomObject]@{ SurName = "Smit99" },
    [PSCustomObject]@{ SurName = "Smit0" },
    [PSCustomObject]@{ SurName = "Smith1" },
    [PSCustomObject]@{ SurName = "Smith11" },
    [PSCustomObject]@{ SurName = "Smit1" },
    [PSCustomObject]@{ SurName = "Smit11abcdefg" },
    [PSCustomObject]@{ SurName = "Smit99999999" },
    [PSCustomObject]@{ SurName = "Smit99999999AAAAA" },
    [PSCustomObject]@{ SurName = "Smit9A999999AAAAA" },
    [PSCustomObject]@{ SurName = "SmitA9999999AAAAA" },
    [PSCustomObject]@{ SurName = "Smit0" },
    [PSCustomObject]@{ SurName = "Smith1" },
    [PSCustomObject]@{ SurName = "Smith11" },
    [PSCustomObject]@{ SurName = "Smith19" },
    [PSCustomObject]@{ SurName = "Smith00" },
    [PSCustomObject]@{ SurName = "Smith99" },
    [PSCustomObject]@{ SurName = "Smith1" },
    [PSCustomObject]@{ SurName = "Smith1" },
    [PSCustomObject]@{ SurName = "Jone" },
    [PSCustomObject]@{ SurName = "Brown" },
    [PSCustomObject]@{ SurName = "Wils" }
    [PSCustomObject]@{ SurName = "Smit" },
    [PSCustomObject]@{ SurName = "Smith" },
    [PSCustomObject]@{ SurName = "Jone" },
    [PSCustomObject]@{ SurName = "Brown" },
    [PSCustomObject]@{ SurName = "Wils" }
)

# Filter users based on the condition
$FilteredUsers = $Users | Where-Object { $_.SurName -like $InputUser -or $_.SurName -match "^$([regex]::Escape($InputUser))(?:\d{1,2}.*)?$" }
#$MatchingUsers = Get-AdUser -Filter "(Surname -like '$User*')" | Where-Object {$_.SurName -Match '[0-9][0-9]*'} | Select-Object SamAccountName, GivenName, SurName, Name
# Display the filtered users
$FilteredUsers

With this result:

PS C:\WINDOWS\system32> C:\Powershell\Demo Names and Numbers xx.ps1

SurName          
-------          
Smit             
Smit1            
Smit11           
Smit99           
Smit0            
Smit1            
Smit11abcdefg    
Smit99999999     
Smit99999999AAAAA
Smit9A999999AAAAA
Smit0            
Smit             



PS C:\WINDOWS\system32>
1 Like