Charlie
Charlie

Reputation: 31

Where-Object square bracket column name

How to filter a PowerShell object that contains a square bracket column name?

for example:

$data | select-object DisplayName, ``[Custom.Class`].Name

would return:

DisplayName [Custom.Class].Name
Cat Animal
Toyota Car
daisy Plant
Honda Car

If i wanted to filter $data to list only [Custom.Class].Name = Car
How can I filter it?

I tried
$data | Where-Object {$_.``[Custom.Class`].Name -eq 'Car'}
but it returned an error
Missing property name after reference operator.

Tried
$data | Where-Object {$_."[Custom.Class].Name" -eq 'Car'}
but returned nothing

I am expecting to list only the filtered data on the column with a bracket name

Upvotes: 3

Views: 145

Answers (1)

mklement0
mklement0

Reputation: 439932

You're seeing a bug in Select-Object, reported a while back in GitHub issue #17068:

  • In property names (possibly positionally implied -Property arguments) that contain wildcard metacharacters meant to be interpreted verbatim - notably [ and ] - attempting to escape them with ` mistakenly causes the ` chars. to be retained as part of the resulting property name.

    • That is, ``[Custom.Class``].Name (which is the same as '`[Custom.Class`].Name') tries to select a property named verbatim `[Custom.Class`].Name from the input objects, and in their absence reports $null values.

    • Note that the form in the question, ``[Custom.Class`].Name (which is the same as '`[Custom.Class].Name') is still a wildcard expression due to the effectively unescaped ], albeit a broken one, and therefore matches none of the input properties and is simply omitted from the output objects.

  • Incidentally, the same applies to the -Property and -MemberName parameters of Where-Object and ForEach-Object, respectively, when using simplified syntax.

As a workaround, replace:

... | select-object DisplayName, ``[Custom.Class``].Name

with:

... | select-object DisplayName, 
                    @{ Name = '[Custom.Class].Name'; 
                       Expression = { $_.'[Custom.Class].Name' } }

That is, use a calculated property to select the property whose name contains wildcard metacharacters, in which case the property names are not subject to interpretation as wildcard expressions.
(By contrast, Expression = '[Custom.Class].Name', i.e. specifying just the property name as a string, would again be subject to wildcard interpretation.)

Then your 2nd attempt to query the property named [Custom.Class].Name verbatim will work (though you may want to use '...' instead of "..." to enclose the property name, given that string interpolation isn't needed):

$data | Where-Object { $_."[Custom.Class].Name" -eq 'Car'}

Upvotes: 4

Related Questions