Advanced String Filtering

by Jul 14, 2009

In a previous tip, you learned how Select-String can filter string arrays based on a keyword. Have a look:

route print | Select-String 127.0.0.1

However, when you look at the result, you may be surprised. It not only contains the filtered information but also some empty lines. The reason is: Select-String does not return the filtered text information but instead wraps this as MatchInfo objects:

route print | Select-String 127.0.0.1 | Format-Table *

A much better way of filtering string arrays is the -like operator:

(route print) -like '*127.0.0.1*'

This time, the result is a plain string array again and may look similar to this:

PS> (route print) -like '*127.0.0.1*'
127.0.0.0 255.0.0.0 On-link 127.0.0.1 306
127.0.0.1 255.255.255.255 On-link 127.0.0.1 306
127.255.255.255 255.255.255.255 On-link 127.0.0.1 306
224.0.0.0 240.0.0.0 On-link 127.0.0.1 306
255.255.255.255 255.255.255.255 On-link 127.0.0.1 306

As you can see, each line contains pieces of information separated by spaces. If you were interested in picking specific pieces of information, let's say the connection metric (last piece, in this example '306'), you can use the Split() operator built into each string:

(route print) -like '*127.0.0.1*' | ForEach-Object { $_.Split(' ') }

This works. Split uses the split character and separates the information accordingly. Unfortunately, you will get a lot of empty lines because the pieces of information are separated by a number of spaces, not just one.

Fortunately, Split() supports an advanced option to remove empty entries:

(route print) -like '*127.0.0.1*' | ForEach-Object { $_.Split(' ',
[StringSplitOptions]'RemoveEmptyEntries') }

Now you get the information without spaces. To pick only a specific "column", remember that the result is an array. Using an index, you specify which array element you'd like to use:

(route print) -like '*127.0.0.1*' | ForEach-Object { $_.Split(' ',
[StringSplitOptions]'RemoveEmptyEntries')[1] }