Home > front end >  Powershell Select-Object Property multiple comparisons same property
Powershell Select-Object Property multiple comparisons same property

Time:08-09

I am using Select-Object to filter a CSV to get the necessary columns. When I use this: $Filter = $Csv | Select-Object ($Csv[0].PSObject.Properties.Name -like "*Results*" it filters all columns and displays everything containing results, this works fine. But how do I get it to keep my first column where the header is "Sample" as well as keeping the results? I have tried without success:

$Filter = $Csv | Select-Object ($Csv[0].PSObject.Properties.Name -like "*Results*" -and $Csv[0].PSObject.Properties.Name -like "Sample")

I understand you can add multiple properties comma separated but I am looking for the same property but with multiple matching parameters.

The output would include a column that have header name "Sample" and columns that would contain the word "Results". They both work individually in the first line of code provided, but how do i make it work together with both matching strings?

Edit: Expected output added

CodePudding user response:

Select-Object's -Property parameter takes an array of property names (see documentation at Select-Object).

Your individual expressions ($Csv[0].PSObject.Properties.Name -like "*Results*" and $Csv[0].PSObject.Properties.Name -like "Sample") each individually return an array of matching columns as expected, but when you -and them together it becomes a boolean expression that returns $true or $false so your Select-Object becomes the equivalent of:

$Filter = $Csv | Select-Object -Property @( $true )

To demonstrate this, we'll use some sample data:

$csv = @"
Sample, Sample2, Something Else, A1Results, ResultsZ2
aaa, bbb, ccc, ddd, eee
"@

$data = $csv | ConvertFrom-Csv

and then see what your individual expressions return:

PS> ($data[0].PSObject.Properties.Name -like "*Results*")
A1Results
ResultsZ2

PS> ($data[0].PSObject.Properties.Name -like "Sample")
Sample

and now we'll try your combined expression:

PS> ($data[0].PSObject.Properties.Name -like "*Results*") -and ($data[0].PSObject.Properties.Name -like "Sample")
True

If you want to generate the list of all matching columns you'll need to combine the two separate lists in a different way - you can add them together and PowerShell will return a new array that contains the two separate arrays concatenated:

PS> ($data[0].PSObject.Properties.Name -like "*Results*")   ($data[0].PSObject.Properties.Name -like "Sample")
A1Results
ResultsZ2
Sample

and then if you plug that back into your original code you get this:

PS> $data | Select-Object ( ($data[0].PSObject.Properties.Name -like "*Results*")   ($data[0].PSObject.Properties.Name -like "Sample") )

A1Results ResultsZ2 Sample
--------- --------- ------
ddd       eee       aaa

Cheeky Update

@mklement0 notes in their answer that the left-hand side of the needs to be an array in order for the addition operator to trigger array concatenation. You can ensure this by coercing the result of the individual expressions into arrays using the Array Subexpression Operator like this:

PS> $data | Select-Object ( @($data[0].PSObject.Properties.Name -like "*Results*")   @($data[0].PSObject.Properties.Name -like "Sample") )

CodePudding user response:

In order to pass multiple property (column) names to the (possibly positionally implied) -Property parameter of the Select-Object cmdlet using an expression ((...)), you must pass a flat array.

To that end, use for concatenation, making sure that (at least) the LHS is an array.

The following places the Sample property first, using @(...), the array-subexpression operator to wrap it in an array:

$Csv |
  Select-Object (@('Sample')   ($Csv[0].PSObject.Properties.Name -like "*Results*"))
  • Related