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*"))