Blue_fish posted a question over on powershellcommunity.org. The source of the question was a mysterious blank entry. This anomaly appeared when he tried to convert a string into an array of individual words. Without his actual code on hand I tried to guess what could cause that. Along the way I typed up the following… thinking out loud with my fingers. Afterwards I realized that this was the kind of information I was looking for when I started out. With that in mind enjoy…
Convert ” abcd efg hi j ” into an array…
(” abcd efg hi j “).split(” “) #done… now remove the blank entries…
(” abcd efg hi j “).split(” “) | where-object {$_ -ne ” “}
Why did that work? Powershells access to the .net framework doesn’t require one to be a .net dev. Far from it instead it brings an incredible amount of power to a usable surface. So how did .split() come to be and why does where work. I think I can explain it… let’s see…
In PowerShell “” refers to a string, obviously, but it’s more than that. A string in PowerShell is a .net object with a type of string, 99.99% of the time that doesn’t matter, but in this case it’s quite pertinent. As a first class object string carries with it many powerful methods free of charge
Parenthesis () have several responsibilities within POSH, but mainly it’s just execution order i.e. (THIRD((FIRST)SECOND(FIRST))). Part of that execution is PowerShell normalizing your data. For example 15 will be cast as an int, asdf as a string, and @(1,2,3,4,5) is an array or integers. As that cast is of objects, this is where all the free posh goodness comes from. Therefore we need to enclose our string in () to perform that cast and have those methods available.
Believe it or not that’s the hard part…
.split(” “) = splits our string into an array of strings using one whitespace as the delimiter.
And that’s how:
” abcd efg hI j “
Transforms into:
@”
abcd
efg
hI
j
“@
Now that you have an array of words all that is left is to remove the false positives. Enter Where-Object, think of where-object (aka where, and ?) as an extremely streamlined if then else filter. {} in PowerShell represent a script block.
A script block is a chunk of code that is executed to its completion before the engine moves on. In other words {} will overrule (). where-object is a bool operator, if the script block evaluates to true then pass the object down the pipeline, else drop the object.
Before where {}
[0] ” ” = False
[1] “abcd” = True
[2] ” “ = False
[3] “efg” = True
[4] ” “ = False
[5] ” “ = False
[6] ” “ = False
[7] “hi” = True
[8] ” “ = False
[9] ” “ = False
[10] “j” = True
After where {}
[0] “abcd”
[2] “efg”
[3] “hi”
[4] “j”
*Only objects that evaluate to $TRUE in the where-object script block are passed down the pipeline. As you can see their really aren’t any “smoke and mirrors” in PowerShell. Instead the team provided a kick ass engine that does 90% of the work for us in a predictable and comprehendible fashion!
~Glenn
I started to post all of this in my response to blue_fish’s post over on powershellcommunity.org, but it occurred to me that I went way to in depth. Sometimes I like to talk myself through the nth degree to prove I know it
Don’t be shy if I screwed something up please let me know. That’s the other part of laying it out to the nth degree if I’m mistaken, you’ll correct me, and we all improve from that exercise!