我如何 select 某些哈希表值但在 powershell 脚本中在线更改其他值

How do I select certain hashtable values but change others in-line in a powershell script

使用管道或其他类型的内联表示法,我想 "select" 散列中的某些值 table 直接到结果,同时更改或设置其他值。

哈希Table

我从散列 table 开始(坦率地说,它像对象一样使用),如下所示:

>$hash

Name               Value
----               -----
System             server-1
Job                Microsoft.PowerShell.Commands.PSWmiJob
Result

有没有办法使用 Select-Object cmdlet(或类似的东西)来设置某些属性的值并传递给其他属性?我想以此结束:

>$hash

Name               Value
----               -----
System             server-1
Job                Microsoft.PowerShell.Commands.PSWmiJob
Result             Good

如果我没有need/want它是内联的,我只是设置Result的值:

$hash.Result = "good"

对于内联解决方案,我总是可以像这样使用 Foreach-Object

$hash | Foreach-Object {@{System=$_.System;Job=$_.Job;Result="Good"}}

或者直接在子表达式中引用 $hash:

${@{System=$hash.System;Job=$hash.Job;Result="Good"}}

然而,当我只处理一个散列 table 时使用 Foreach-Object 似乎是荒谬的,而且两次提及我只想通过的属性非常冗长,然后如果我的 $hash 变量是 $aSignificantlyLongerHashTableVariableName,可能会很笨拙。

如果我使用的是 Powershell 对象...

如果我使用这样的对象:

>$obj

System        Job                                      Result
------        ---                                      ---
server-1      Microsoft.PowerShell.Commands.PSWmiJob             

我会像这样使用 select-object Cmdlet:

>$obj | Select-Object System, Job, @{Name="Result";Expression="Good"}

这将导致

>$obj

System        Job                                      Result
------        ---                                      ---
server-1      Microsoft.PowerShell.Commands.PSWmiJob   Good

Hashtable 和 PSObject 有一些相似的方面(以命名方式包含其他东西的东西),但是据我所知,它们是不兼容的——有没有更接近 Select-Object 的替代方法?我要在这里做什么?

要解析单值对象,请使用:

$hash = @{}
$hash.Add("System",$obj.System)
$hash.Add("Job"=$obj.job)
$hash.Add("Result"="Good")

如果您需要更多对象 - 迭代它们 foreach($o in $obj){$hash.Add()},但在循环之前声明 $hash。

当您使用 Select-Object 并添加一个不存在的列 (属性) 时,您实际上是在创建一个新的 [PSObject] 来包装原始列。您可以明确地执行此操作并使用 [hashtable] 以两种方式启动其属性:

$obj = [PSCustomObject]$hash

$obj = New-Object PSObject -Property $hash

从那里,您可以像往常一样使用 Select-Object。您也可以先操作哈希以获得所需的属性,然后转换为对象并跳过 Select-Object.

严格要求将其作为单行程序,事先没有设置代码并且不修改源哈希,这样的事情可以完成这项工作:

($hash + @{ 'Result' = 'Good' }).GetEnumerator() | ? {$_.Key -in 'Result','System','Job'}

如果您要定期添加一些东西 Result = Good,保存您的小扩展位可能会很方便:

$good = @{ 'Result' = 'Good' }

然后你的一行变成:

($hash + $good).GetEnumerator() | ? {$_.Key -in 'Result','System','Job'}

编辑: 正如您在下面的评论中指出的那样,如果 Result 存在于散列中,则单行代码将会消失。这个版本有点 safer/more 明确,更直接地映射到你在 PSObjects 上用 Select-Object 描述的精神:

(($hash).GetEnumerator() | ? {$_.Key -in 'System','Job'}) + @{'Result' = 'Good'}

仍然不是世界上最漂亮的东西,但它完成了工作。

如果您只需要在哈希中添加或更新一个键 table:

$hash.Result += 'Good'

如果 Result 键存在,它的值将被设置为 'Good'。如果不存在,将添加该值。