I have an object with spaces in their properties names. I want to Select-Object @{n='NewName';e={$_.'Old Name'}} for every NoteProperty. Since there is a lot of them, I created this function. Running this code will return an array of hash tables but I can't get the old name $col to be replaced with the actual old name. I think it's because it's bound to a new execution context but I can't make it to work.
function Rename-Columns {
# Array of HashTable splat to rename columns in Select-Object (TSQL SELECT [col with space] as colwithspace)
param (
[string[]]$Columns,
[hashtable]$RenamePattern = @{Replace='\s|\:|\.|\+|\|';With=''} # remove unwanted cars
)
$return = @()
foreach ($col in $Columns) {
$newName = $col -replace $RenamePattern['Replace'], $RenamePattern['With']
$return += @{n="$newName";e={$_.'"$col"'}} # <- can't replace $col
}
$return
}
Your current approach can't work because by the time you pass the
{$_."$col"}block toSelect-Object,$colno longer resolves to the value it did when you created the scriptblock inside the loop.In order to bind the current iterator value of
$colto the expression block, you need a closure:GetNewClosure()will see that the$colvariable exists in the scope where it was called, and so it copies its value and stores it along-side the scriptblock.As a result, when
Select-Objectexecutes the property expression (at a later time), the scriptblock "remembers" the original value and$colresolves correctly/as expected.With sample data:
It yields the expected result (spaces replaced in all names):