Powershell regular expression problem

I have a regular Expression challenge.
In the code that I've added, I anticipate two not identical matches, but instead I get two identical matches:

Expected Output:
Name Value  
---- -----  
1    00:00:03
0    09:40:23

Actual output:
Name Value  
---- -----  
1    09:40:23
0    09:40:23

Can anyone explain why this happens, and in this help me pass Saint Peter.

Thank you!
Anders
$string = "(09:40:23)(00:00:03)" 

#$string = "(00:00:03)" # Using this returns one match, so the regular expression is not totally wasted

$string -match "([0-3][0-9]:[0-5][0-9]:[0-5][0-9])" |Out-Null
$matches |ft -autosize

Open in new window

LVL 1
jmateknikAsked:
Who is Participating?
 
käµfm³d 👽Connect With a Mentor Commented:
Here's one that's a bit more "to the point" WRT its output (sorry, I don't know all the fancy PS cmdlets, so it might be a tad bulky!):
$string = "(09:40:23)(00:00:03)" 

#$string = "(00:00:03)" # Using this returns one match, so the regular expression is not totally wasted

$matches = [System.Text.RegularExpressions.Regex]::Matches($string, "[0-3][0-9]:[0-5][0-9]:[0-5][0-9]")

$list = @()

foreach ($match in $matches)
{
    $list += $match.Value
}

$list | ft -autosize

Open in new window

0
 
Shinesh PremrajanEngineering ManagerCommented:
Now sure how powershell works, i find that since its a string, the multiple matches could be defined as

"([0-3][0-9]:[0-5][0-9]:[0-5][0-9])+"

Hope this helps
0
 
sjklein42Commented:
It may not help but I don't think you need the parens in the pattern on line 5.

$string -match "[0-3][0-9]:[0-5][0-9]:[0-5][0-9]" |Out-Null

Open in new window

0
Worried about phishing attacks?

90% of attacks start with a phish. It’s critical that IT admins and MSSPs have the right security in place to protect their end users from these phishing attacks. Check out our latest feature brief for tips and tricks to keep your employees off a hackers line!

 
käµfm³d 👽Commented:
The reason you see two "matches" is due to the parentheses. If you'll notice, there should be a number preceding the match (see screenshot). This number refers to the "capture group" the match belongs to. Zero represents the overall match, and one refers to the first capture group, which you set when you included the parentheses. PS shows you both groups. Removing the parentheses results in only the overall match (group 0) being displayed (2nd execution in screenshot).
Untitled.png
0
 
käµfm³d 👽Commented:
As further explanation, the more capturing parentheses you add, the more groups that will show up. Doubling-up the parentheses will result in 3 identical "matches" (first execution below). Shifting the parentheses around, however, will give you different results (second execution).
Untitled.png
0
 
käµfm³d 👽Commented:
Here was the script for the execution above:

Execution 1
$string = "(09:40:23)(00:00:03)" 

#$string = "(00:00:03)" # Using this returns one match, so the regular expression is not totally wasted

$string -match "(([0-3][0-9]:[0-5][0-9]:[0-5][0-9]))" |Out-Null
$matches |ft -autosize

Open in new window



Execution 2
$string = "(09:40:23)(00:00:03)" 

#$string = "(00:00:03)" # Using this returns one match, so the regular expression is not totally wasted

$string -match "([0-3][0-9]):([0-5][0-9]):[0-5][0-9]" |Out-Null
$matches |ft -autosize

Open in new window

0
 
käµfm³d 👽Commented:
One last thing  = )


I think you may have been trying to match the parentheses which are part of your data. What you need to be aware of is that parentheses have special meaning (as mentioned above) within regex; as such, you need to "escape" them (by using a preceding backslash) when you want them to be matched as a literal character. Here is a modified version of your pattern which would match the parentheses:
$string -match "\([0-3][0-9]:[0-5][0-9]:[0-5][0-9]\)" |Out-Null

Open in new window

0
 
jmateknikAuthor Commented:
shinuq and sjklein42:
Thanks for your suggestions but it didn't solve it.

kaufmed:
Thanks for pulling your energy in the project.
I understand your explanation to the grouping/how to use parentheses.

I regret having used parenthesis in the search-string, which gives the impression that I want to capture the time-value WITH the parentheses. Putting the parentheses in the regular expression was merely my own process towards a solution to capture both values/I am aware that capturing the parentheses themselves will need "escaping".

The core-challenge remains unsolved:
How do I capture both time-values ['09:40:23' (being an uninteresting time-value) and '00:00:03' (being a timespan and the value i actually need to get hold of) ].

As pointed in my out-commented line in my first code-example: if the search-string (for testing) only consists of the second value ['00:00:03'] , that value is indeed captured by the regular expression presented, so it might just be a slight correction to the regular expression, something like telling the regular expression to be greedy.
0
 
käµfm³d 👽Commented:
I am by no means a PS guru, but I believe -match only confirms the first match, if any. There may be a more efficient way to do what you want, but what I am familiar with would be something like:
$string = "(09:40:23)(00:00:03)" 

#$string = "(00:00:03)" # Using this returns one match, so the regular expression is not totally wasted

$matches = [System.Text.RegularExpressions.Regex]::Matches($string, "[0-3][0-9]:[0-5][0-9]:[0-5][0-9]")

$matches |ft -autosize

Open in new window

0
 
jmateknikAuthor Commented:
With your help I came on the right track. The .NET variant (as opposed to the  -match operator in combination with $matches) is a more wealthy object to deal with.

I ended up with the following code, that is a slight modification of your code:
 
[string] $string = "(09:40:23)(00:00:03)"
[Regex]$TimeRegex = "[0-3][0-9]:[0-5][0-9]:[0-5][0-9]"

[array]$matches	= $TimeRegex.matches($string) | ForEach-Object { $_.value }
[int]$Values = $Matches.length

if ($Values -eq 2) { $Matches[1] }
else { "Plan B" }

Open in new window

Thank you for your helpfullness along the way kaufmed - you are soon to be even more wealthy Genius :)
Thank you shinuq and sjklein42 for showing your face...
0
 
käµfm³d 👽Commented:
Glad you got it working   = )
0
 
jmateknikAuthor Commented:
This link helped me btw:
Powershell Tutorial chapter-13-text-and-regular-expressions

It states:
It's true here, too, that -match finds only the first match. If your raw text has several occurrences of the keyword, use a RegEx object again:
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.