Jump to content

Powershell - match, like, contains not working with @ symbol


0phoi5

Recommended Posts

Hi guys,

I have the following PowerShell script, which finds the list of groups a user is a member of, formats them to name only, and then is supposed to list yes or no to which groups begin with the '@' symbol;

$CurrentGroups = Get-ADuser JOEBLOGGS -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name}

foreach($Group in $CurrentGroups) {
if("$Group" -match "`@") { echo Yep $Group }
else { echo Nope $Group }}

 

User JOEBLOGGS is a member of;

  • @Testone
  • @Testtwo
  • Testthree
  • Testfour

 

On running this script, I would expect the output to be;

Yep
@Testone
Yep
@Testtwo
Nope
Testthree
Nope
Testfour

However, it instead states 'Yep' to all of them, not just the groups beginning with an '@' symbol.

 

I have tried -like, -match, -contains as well as "\@", "@*" and "@". None work correctly.

 

If I run -match "@Test", this works fine, but not all of the groups in our AD that begin with an @ symbol follow with the same digits, so I need this to work with just searching for all groups that begin with an @ symbol.

Thank you.

Link to comment
Share on other sites

  • 4 weeks later...
On 2/6/2017 at 1:44 AM, haze1434 said:

Ah!


`@[A-Za-z0-9] 

Success!!

Ok, but can you answer WHY it failed when it was just "`@"?

Because WHY it failed is more important than how to make it work.

I don't know how often you code, but sometimes it's good to build your own debuggers into code:

Thought about it for a moment and the why is the match is you are NOT matching $Group but matching $CurrentGroups.

I haven't thought of a way to test this yet, but it's the only logical way I can think of why your first code failed.

Edited by IDNeon
Link to comment
Share on other sites

On ‎03‎/‎03‎/‎2017 at 10:40 PM, IDNeon said:

Because WHY it failed is more important than how to make it work.

Not always. We don't understand why Quantum Mechanics works, but we're making Quantum Computers anyway.

I agree that it's important to find out why something works, yes, but not the most important thing. Sometimes deadlines and requirements come first, stuff like that comes after. No ideal, agreed, but that's life.

Edited by haze1434
Link to comment
Share on other sites

On ‎03‎/‎03‎/‎2017 at 10:40 PM, IDNeon said:

Thought about it for a moment and the why is the match is you are NOT matching $Group but matching $CurrentGroups.

Not sure what you mean, sorry.

$Group is a variable already recognised by PowerShell - The line 'foreach($Group in $CurrentGroups)' works fine.

Link to comment
Share on other sites

Doesn't -match take a regular expression? If so have you tried "^@" to match a string starting with the @ symbol?

What's really interesting though is that you got it returning true for all your groups whether they contained an @ symbol or not, which is something I haven't been able to recreate. e.g.

$x = @("@test", "test2", "asd@test3");

foreach ($group in $x) {
  if ("$group" -match "`@") {
    echo "yep $group"
  } else {
    echo "Nope $group"
  }
}

results in

yep @test
Nope test2
yep asd@test3

while

$x = @("@test", "test2", "asd@test3");

foreach ($group in $x) {
  if ("$group" -match "^@") {
    echo "yep $group"
  } else {
    echo "Nope $group"
  }
}

results in 

yep @test
Nope test2
Nope asd@test3

 

Link to comment
Share on other sites

$y = Get-ADuser JOEBLOGGS -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name}

foreach ($group in $y) {

if ("$group" -match "^@") {

echo "yep $group"

} else {

echo "Nope $group"

}

}

yep @{Name=@Testone}

yep @{Name=@Testtwo}

yep @{Name=Testthree}

yep @{Name=Testfour}

Edited by haze1434
Link to comment
Share on other sites

No luck, as above. Must be something to do with the way it's parsing Get-ADuser? (rather than setting the variables without Get-ADuser)

I assume I'm doing something wrong here: $y = Get-ADuser JOEBLOGGS -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name}

Edited by haze1434
Link to comment
Share on other sites

Seeing your output suddenly makes it all make sense. The $group variable isn't a simple string, it's actually an object with a Name property. When you put it in double quotes Powershell produces a stringified version of the object, which starts with the @ symbol (e.g. "@{Name=@Testone}". You then do a regular expression match against that string, which sees the first character as the @ symbol, which is matches what it's looking for exactly.

I don't have access to an active directory to test, but try matching against the $group object's Name propery instead, e.g.

$y = Get-ADuser JOEBLOGGS -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name}

foreach ($group in $y) {
    if ($group.Name -match "^@") {
        echo "yep $group"

    } else {
        echo "Nope $group"
    }
}

 

Link to comment
Share on other sites

3 hours ago, haze1434 said:

Not sure what you mean, sorry.

$Group is a variable already recognised by PowerShell - The line 'foreach($Group in $CurrentGroups)' works fine.

I was in the middle of a thought process (and editing my previous posts to update) but got busy, usually that happens and you'll just have to move on from those posts when I don't get back to them.

What I was trying to show before I had to abandon it was what the value of $Group actually was when -match compares it to your expression.

I wanted to see if the $Group value was carrying the @ through its comparison.

I was in the process of writing a little debugger for that but got busy and this is the first time in 3 days I have had time to revisit this thread.

Link to comment
Share on other sites

21 minutes ago, Jason Cooper said:

Seeing your output suddenly makes it all make sense. The $group variable isn't a simple string, it's actually an object with a Name property. When you put it in double quotes Powershell produces a stringified version of the object, which starts with the @ symbol (e.g. "@{Name=@Testone}". You then do a regular expression match against that string, which sees the first character as the @ symbol, which is matches what it's looking for exactly.

I don't have access to an active directory to test, but try matching against the $group object's Name propery instead, e.g.


$y = Get-ADuser JOEBLOGGS -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name}

foreach ($group in $y) {
    if ($group.Name -match "^@") {
        echo "yep $group"

    } else {
        echo "Nope $group"
    }
}

 

Not sure that's the answer though EITHER?


Because the OP provided a solution "`@[a-zA-Z0-9]" which has an intended result

This means your explanation does not explain why his solution would work to segregate as it did?

Link to comment
Share on other sites

17 minutes ago, IDNeon said:

Not sure that's the answer though EITHER?


Because the OP provided a solution "`@[a-zA-Z0-9]" which has an intended result

This means your explanation does not explain why his solution would work to segregate as it did?

Actually it does explain why it worked, but I'll go into it in a bit more depth.

When using the $Group in double quotes it stringifys the value of the object so we have four strings

@{Name=@Testone}
@{Name=@Testtwo}
@{Name=Testthree}
@{Name=Testfour}

The regular expression the OP provided as a solution is looking for an @ symbol followed by a character that is in the range or a - z, A - Z or 0 - 9. While all four strings start with an @ symbol those are immediately followed by an open brace '{' which doesn't match the pattern that the regular expression is looking for. The first and second strings have another @ symbol which does match the pattern as they're followed by the letter 'T' which is in the range being matched.

The OP's solution however doesn't actually meet the criteria of only matching groups starting with an @ symbol as any groups that contain an @ symbol in the middle of their name (e.g. Test@five) as it will be matched by the "`@[a-zA-Z0-0]" regular expression as well.

Link to comment
Share on other sites

20 minutes ago, Jason Cooper said:

Actually it does explain why it worked, but I'll go into it in a bit more depth.

When using the $Group in double quotes it stringifys the value of the object so we have four strings


@{Name=@Testone}
@{Name=@Testtwo}
@{Name=Testthree}
@{Name=Testfour}

The regular expression the OP provided as a solution is looking for an @ symbol followed by a character that is in the range or a - z, A - Z or 0 - 9. While all four strings start with an @ symbol those are immediately followed by an open brace '{' which doesn't match the pattern that the regular expression is looking for. The first and second strings have another @ symbol which does match the pattern as they're followed by the letter 'T' which is in the range being matched.

The OP's solution however doesn't actually meet the criteria of only matching groups starting with an @ symbol as any groups that contain an @ symbol in the middle of their name (e.g. Test@five) as it will be matched by the "`@[a-zA-Z0-0]" regular expression as well.

Brilliant thanks for that clarification.

That's why I wanted to get deeper into this, my gut feeling was that the big-picture wasn't well understood and as you said, the "solution" was really not a solution.

Reason I wanted to pursue that was it's in those patch-jobs that problems are created.  Your explanation would provide for a completely exact answer.

Edited by IDNeon
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...