假设我有一个这样的对象:
$test = @{
ThisIsTheFirstColumn = "ValueInFirstColumn";
ThisIsTheSecondColumn = "ValueInSecondColumn"
}
我想以:
$test = @{
THIS_IS_THE_FIRST_COLUMN = "ValueInFirstColumn";
THIS_IS_THE_SECOND_COLUMN = "ValueInSecondColumn"
}
无需手动编码新列名。
这向我展示了我想要的值:
$test.PsObject.Properties | where-object { $_.Name -eq "Keys" } | select -expand value | foreach{ ($_.substring(0,1).toupper() + $_.substring(1) -creplace '[^p{Ll}s]', '_$&').Trim("_").ToUpper()} | Out-Host
这导致:
THIS_IS_THE_FIRST_COLUMN
THIS_IS_THE_SECOND_COLUMN
但现在我似乎无法弄清楚如何将这些新值重新分配给对象。
您可以就地修改哈希表$test
,如下所示:
foreach($key in @($test.Keys)) { # !! @(...) is required - see below.
$value = $test[$key] # save value
$test.Remove($key) # remove old entry
# Recreate the entry with the transformed name.
$test[($key -creplace '(?<!^)p{Lu}', '_$&').ToUpper()] = $value
}
@($test.Keys)
从现有的哈希表键创建一个数组;@(...)
确保将密钥集合复制到静态数组,因为直接在修改同一哈希表的循环中使用.Keys
属性会中断。
循环主体保存手头输入键的值,然后删除其旧名称下的条目。[1]
然后,使用所需的名称转换在其新键名下重新创建条目:
$key -creplace '(?<!^)p{Lu}
匹配给定键中的每个大写字母(p{Lu}
),除了字符串的开头((?<!^)
),并将其替换为后跟该字母(_$&
)的_
;将结果转换为大写(.ToUpper()
)得到所需的名称。
[1]在添加重命名条目之前删除旧条目可以避免单个单词名称的问题,例如Simplest
,由于 PowerShell 中 hasthables 不区分大小写,其转换后的名称SIMPLEST
被视为相同名称。因此,在条目Simplest
仍然存在时为条目SIMPLEST
赋值实际上以现有条目为目标,然后后续$test.Remove($key)
将简单地删除该条目,而无需添加新条目。
向约瑟夫Z指出问题致敬。
我想知道是否可以在原始对象上就地执行此操作?
($test.PsObject.Properties|Where-Object {$_.Name -eq "Keys"}).IsSettable
说False
.因此,您需要分两步完成,如下所示:
$test = @{
ThisIsTheFirstColumn = "ValueInFirstColumn";
ThisIsTheSecondColumn = "ValueInSecondColumn"
}
$auxarr = $test.PsObject.Properties |
Where-Object { $_.Name -eq "Keys" } |
select -ExpandProperty value
$auxarr | ForEach-Object {
$aux = ($_.substring(0,1).toupper() +
$_.substring(1) -creplace '[^p{Ll}s]', '_$&').Trim("_").ToUpper()
$test.ADD( $aux, $test.$_)
$test.Remove( $_)
}
$test
两步方法是必需的,因为尝试在唯一的管道中执行REMOVE
和ADD
方法会导致以下错误:
select : Collection was modified; enumeration operation may not execute.
编辑。不幸的是,上述解决方案在单字Pascal案例键的情况下会失败,例如对于Simplest = "ValueInSimplest"
。以下是改进的脚本:
$test = @{
ThisIsTheFirstColumn = "ValueInFirstColumn";
ThisIsTheSecondColumn = "ValueInSecondColumn"
Simplest = "ValueInSimplest" # the simplest (one word) PascalCase
}
$auxarr = $test.PsObject.Properties |
Where-Object { $_.Name -eq "Keys" } |
select -ExpandProperty value
$auxarr | ForEach-Object {
$aux = ($_.substring(0,1).toupper() +
$_.substring(1) -creplace '[^p{Ll}s]', '_$&').Trim("_").ToUpper()
$newvalue = $test.$_
$test.Remove( $_)
$test.Add( $aux, $newvalue)
}
$test
这似乎有效。 不过,我最终将东西放在一个新的哈希表中。
$test = @{
ThisIsTheFirstColumn = "ValueInFirstColumn";
ThisIsTheSecondColumn = "ValueInSecondColumn"
}
$test2=@{}
$test.PsObject.Properties |
where-object { $_.Name -eq "Keys" } |
select -expand value | foreach{ $originalPropertyName=$_
$prop=($_.substring(0,1).toupper() + $_.substring(1) -creplace '[^p{Ll}s]', '_$&').Trim("_").ToUpper()
$test2.Add($prop,$test[$originalPropertyName])
}
$test2