假设我有一个这样的对象:
$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
但是现在我似乎无法弄清楚如何将这些新值分配回该对象。
答案 0 :(得分:6)
您可以按如下方式修改哈希表operator=
:
$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)
确保将键集合复制到静态数组,因为直接在修改同一哈希表的循环中使用@(...)
属性会破坏。
循环主体保存手头输入键的值,然后以旧名称删除条目。 [1]
然后使用所需的名称转换以新的键名重新创建该条目:
.Keys
匹配给定键中的每个大写字母($key -creplace '(?<!^)\p{Lu}
),但字符串(\p{Lu}
)的开头除外,并用(?<!^)
替换,后跟{那封信(_
);将结果转换为大写(_$&
)会产生所需的名称。
[1]在添加重命名的条目之前删除 之前的旧条目可避免使用单字名称(例如.ToUpper()
)的问题,其转换后的名称,Simplest
被认为是相同名称,因为在PowerShell中hasthables不区分大小写。因此,在条目SIMPLEST
仍然存在时为条目SIMPLEST
分配一个值实际上是针对 existing 条目,然后随后的Simplest
会简单地删除该条目,而无需添加了一个新的。
提示JosefZ指出问题所在。
答案 1 :(得分:2)
这似乎有效。我最终还是把东西放到了新的哈希表中。
$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
答案 2 :(得分:2)
I wonder if it is possible to do it in place on the original object?
($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 Case 的情况下会失败,例如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