Using powershell Select-Object with a property that contains a square bracket

914 Views Asked by At

I am getting a dataset back from a SSAS model via AdomdClient which gives me an object with properties that have names with square brackets in them. This is preventing me from being able to use Select-Object to only select a subset of properties (or more specifically to use calculated properties to rename them so that they match another dataset/obj)

I am aware of issues around using square brackets in file names and have tried escaping the brackets. Ideally I would like to learn of a powershell way to handle these properties, although any answers that explain a way to get the adomdclient to return the data back without the brackets would also be very helpful for my specific goal of renaming the properties.

This code snippet below can recreate what I am seeing without the SSAS/adomdclient dependencies. I am using powershell 5.1 for this code due to a assembly dependency:

$bracketedTestObj = New-Object PSObject -Property @{
    "MyProperty[WithBrackets]" = "bracketedValue"
    "MyPropertyWithoutBrackets" = "nonbracketedValue"
}

Write-host "The whole obj"
$bracketedTestObj | ft

Write-host "Select just the non bracketed property"
$bracketedTestObj | select-Object "MyPropertyWithoutBrackets" | ft

# I cannot figure out how to escape the [] and select only the bracketed property 
Write-host "Select just the bracketed property"
$bracketedTestObj | select-Object "MyProperty[WithBrackets]" | ft

Write-host "Select just the bracketed property, 1 backtick"
$bracketedTestObj | select-Object "MyProperty`[WithBrackets`]" | ft

Write-host "Select just the bracketed property, 2 backtick"
$bracketedTestObj | select-Object "MyProperty``[WithBrackets``]" | ft

Write-host "Select just the bracketed property, 3 backtick"
$bracketedTestObj | select-Object "MyProperty```[WithBrackets```]" | ft

Write-host "Select just the bracketed property, 4 backtick"
$bracketedTestObj | select-Object "MyProperty````[WithBrackets````]" | ft

results (I did not include the results with more than ` backtick, but the result is the same:

The whole obj

MyPropertyWithoutBrackets MyProperty[WithBrackets]
------------------------- ------------------------
nonbracketedValue         bracketedValue          


Select just the non bracketed property

MyPropertyWithoutBrackets
-------------------------
nonbracketedValue        


Select just the bracketed property

MyProperty[WithBrackets]
------------------------
                        


Select just the bracketed property, 1 backtick

MyProperty[WithBrackets]
------------------------
                        
2

There are 2 best solutions below

0
Mathias R. Jessen On BEST ANSWER

To my best knowledge, there's no way to force Select-Object to not attempt to expand wildcard sequences in property names.

Safest workaround is to use a calculated property that evaluates the target property on the input item:

$object = [pscustomobject]@{
  'MyProperty[WithBrackets]' = 123
  'OtherProperty' = 456
}

$object |Select-Object @{Name='MyProperty[WithBrackets]';Expression={$_.'MyProperty[WithBrackets]'}}

To keep it DRY, you might want to write a small utility function to generate such calculated property definitions:

function New-LiteralPropertySelector {
  param([string[]]$PropertyName)

  foreach($name in $PropertyName){
    if([WildcardPattern]::ContainsWildcardCharacters($name)){
      # Property name contains wildcard characters -> special handling required
      Write-Output @{Name=$name;Expression={$_.$name}.GetNewClosure()}
    }
    else {
      # No wildcards, return as-is
      Write-Output $name
    }
  }
}

Now you can do:

$object = [pscustomobject]@{
  'MyProperty[WithBrackets]' = 123
  'OtherProperty' = 456
  'ImportantProperty' = 789
}

$object |Select-Object @(New-LiteralPropertySelector 'MyProperty[WithBrackets]','ImportantProperty')

And get the expected results:

MyProperty[WithBrackets] ImportantProperty
------------------------ -----------------
                     123               789
3
TessellatingHeckler On

If the brackets are part of the wildcarding, like Select-Object MyProp*, then maybe...

PS C:\> $bracketedTestObj|Select-Object 'MyProperty[[]WithBrackets[]]'

MyProperty[WithBrackets]
------------------------
bracketedValue

[Edit: this feels like it shouldn't work, like the []] should break it, or the whole outer [...] should take any of the letters inside it in scrambled order, but quick testing neither of those problems seems to happen].

A workaround, wildcards that match a single character:

Select-Object "MyProperty?WithBrackets?"