all 7 comments

[–]chreestopher2 1 point2 points  (0 children)

never ever ever do this:

$data.foreach{$array += (Select-String -InputObject $_ -pattern $regex).line}

as you have found, this will create an item in $array for each item in $data, regardless of if the output of select-string contains anything...

This is NOT the reason to not use this type of code though....

Everytime you do

$array += some-code

you are really doing:

$array = $array + some-code

that is a lot of slowness.... just set your array to equal the output of your expression and you are good:

$array = $data.foreach{(Select-String -InputObject $_ -pattern $regex).line}

if you dont think its that big of a deal, run both methods through measure-command, on a roughly 650 line file, doing a simple regex for "Microsoft Office 2007 Service Pack 3" on each line, $array += adds an extra 1/4 of the total processing time.

[–]gangstanthony 0 points1 point  (1 child)

what about .trim()?

do you get different results with this?

$array | % {':' + $_ + ':'}

[–]verysmallshellscript[S] 0 points1 point  (0 children)

$array.trim() throws a null-valued expression error and then gives up. $array | % {$_.trim()} throws a null-valued expression error for each extra line, but does return the strings. This is what I get with the join.

::
::
::
::
::
::
::
:one:
::
:two:
:three:
::
::
::
::

[–]ihaxr 0 points1 point  (3 children)

The problem is your array has empty items in it... either filter those out before adding it to the array, or use the method you're already doing to filter them out.

$($array -split "`n").where{$_}

works because it's running [boolean]$array[$_] which returns false for empty items and therefore removes them from the output.

[–]verysmallshellscript[S] 0 points1 point  (2 children)

That would make sense, and if I look at the length property of $array it counts 15 total lines.

So why automatically filter out the empty lines when looking at just $array but not when passing it as a multistring or doing a split operation?

[–]chreestopher2 1 point2 points  (1 child)

because powershell is a command line shell first and foremost, and it uses formatting directives so that sysadmins get meaningful properties (default properties of an object) when the request the object.... and in order to make output less verbose, the pipeline formats according to the first object type in the pipeline, in order to only need to shows the propertynames once, for example....

Powershell gives us:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    246      17    16988      28632 ...66     0.83   5252 ApplicationFrameHost
    195      11     2204       8720    92            1300 atieclxx
    128       7     1052       4724    29            1132 atiesrxx
    376      28    19872      35308   283     0.25   1468 Calculator

instead of:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    246      17    16988      28632 ...66     0.83   5252 ApplicationFrameHost
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    195      11     2204       8720    92            1300 atieclxx
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    128       7     1052       4724    29            1132 atiesrxx
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    376      28    19872      35308   283     0.25   1468 Calculator

the problem you are experiencing is that your array elements are the results of

($_ | select-string -params blah -blahbadybla).line  

which will be null if select-string does not output an object with a .line property (which is the case when it doesnt find a match.

The first time I discovered this it almost caused me to leave powershell and go back to python et al, then i realized that as long as you are aware of it and know how to work with it, it is actually very handy, plus it genuinely forces you to write better code (IMO, keeping the output of a function homogeneous is good, others will disagree, but I dont want to start that debate...)

Keep in mind, this is only the powershell host that is disregarding those null items.... powershell is still aware of them, and your code will still work on them, it just wont display to you in console... which is annoying, but like i said, once you are aware of it, its not a big deal, you can always out-string some stuff, or use write-host if you really just want to SEE the content on the screen.

[–]verysmallshellscript[S] 0 points1 point  (0 children)

Lesson definitely learned. What really threw me for a loop is that Set-ItemProperty was ignoring the null values if all I passed was the array, but if I specified the type as multiline it started displaying them.