(This post is the second in my Solving Problems with PowerShell series.)
Problem: Extract list of IP addresses and ping them
So I had a bunch of text in a webpage form which looked like this:
[172.16.16.139] (2.0.39) [172.16.16.31] (2.0.40) [172.16.16.189] (2.0.40) [172.16.16.156] (2.0.45) [172.16.15.89] (2.0.46) [172.16.16.81] (2.0.46) [172.16.16.73] (2.0.47) [172.16.16.31] (2.0.48) [172.16.15.106] (2.0.49) [172.16.16.238] (2.0.49) [172.16.15.14] (2.0.54) [172.16.15.79] (2.0.54)
My goal was to ping each host to see if they were alive. Here’s how I went about that process.
Step One – Get the data into PowerShell
After copying the above into the clipboard, I used PowerShell’s “here-string” feature to quickly get the list into a variable. I just typed this into a console window:
$a = @"
Then I hit enter, then ctrl-V, followed by another enter (so that its on a line by itself) and this:
"@
Now, $a contains the string I want to match against.
Step Two – Parse the text
This one was easier than you may think because I had done some prep some months ago for just such an occasion. There’s this really cool tool Expresso (website appears down, uh oh! google similar results to the rescue!) which helps you to graphically create a regular expression which can then be used to for parsing text. That tool came with a library of commonly used regular expressions, one of which was made to match IP addresses. To save time for when I might need to use it, I have this in my profile which loads when PowerShell is started:
New-Variable -Name RegexIP -Force `
-Description "A regular expression object which matches and validates IP addresses." `
-Value ([regex]'(?<First>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Second>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Third>2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?<Fourth>2[0-4]\d|25[0-5]|[01]?\d\d?)')
With that in hand, here’s how I parsed the text which was now in the $a variable:
97# $regexip.Matches($a) | select value
Value
-----
172.16.16.139
172.16.16.170
172.16.16.31
172.16.16.189
172.16.16.57
172.16.16.156
172.16.15.89
172.16.16.81
172.16.16.73
172.16.16.31
172.16.16.80
172.16.15.106
172.16.16.238
172.16.15.14
172.16.15.79
Step Three – Ping the male progeny of female dogs!
And lastly, pipe the mess to the Ping-Computer cmdlet which is available from SAPIEN’s PowerShell Extensions (PshX-SAPIEN).
PS > $regexip.Matches($a) | select -ExpandProperty value | Ping-Computer ComputerName StatusCode ResponseTime ProtocolAddress ------------ ---------- ------------ --------------- 172.16.16.139 0 0 172.16.16.139 172.16.16.170 0 0 172.16.16.170 172.16.16.31 0 0 172.16.16.31 172.16.16.189 0 0 172.16.16.189 172.16.16.57 0 1 172.16.16.57 172.16.16.156 0 0 172.16.16.156 172.16.15.89 0 0 172.16.15.89 172.16.16.81 0 0 172.16.16.81 172.16.16.73 0 0 172.16.16.73 172.16.16.31 0 0 172.16.16.31 172.16.16.80 0 0 172.16.16.80 172.16.15.106 0 0 172.16.15.106 172.16.16.238 0 0 172.16.16.238 172.16.15.14 0 0 172.16.15.14 172.16.15.79 0 0 172.16.15.79
Instead of using Select-Object –ExpandProperty, I could have used the Foreach-Object cmdlet in a loop like this:
PS > $regexip.Matches($a) | % { Ping-Computer $_.Value }
Same end result, but I have been using select –exp a lot lately and have gotten used to that technique. To each his own.
So that’s it! I hope this walkthrough helps you out with a problem that you need to solve.
I also use http://regexlib.com/default.aspx as a source for Regex expressions. I find regular expressions tedious to develop so I’m happy to “re-provision” someone else’s hard work.
Thanks for the link, Jeff!