Solved

Powershell regular expression problem

Posted on 2011-02-17
12
1,123 Views
Last Modified: 2012-05-11
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

0
Comment
Question by:jmateknik
12 Comments
 
LVL 17

Expert Comment

by:shinuq
ID: 34915099
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
 
LVL 16

Expert Comment

by:sjklein42
ID: 34915195
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34915797
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34915864
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34915873
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34916247
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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 1

Author Comment

by:jmateknik
ID: 34916584
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34916994
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
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 34917226
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
 
LVL 1

Author Comment

by:jmateknik
ID: 34919974
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
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34921222
Glad you got it working   = )
0
 
LVL 1

Author Comment

by:jmateknik
ID: 34921278
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

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Are you one of those front-line IT Service Desk staff fielding calls, replying to emails, all-the-while working to resolve end-user technological nightmares? I am! That's why I have put together this brief overview of tools and techniques I use in o…
Microsoft Windows Server Update Service (WSUS) is free for everyone, but it lacks of some desirable features like send an e-mail to the administrator with the status of all computers on the WSUS server. This article is based on my PowerShell script …
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now