【问题标题】:PowerShell: Adding "rows" to custom objectPowerShell:向自定义对象添加“行”
【发布时间】:2019-05-10 00:48:57
【问题描述】:

我想在 powershell 中创建一个对象来存储有关脚本状态的信息。我可以这样做:

$myScriptObject = 
    @("status", "Selected Operation(s):", "None"), 
     ("status", "Current Operation:", "None"), 
     ("status", "Current Step:", "Prompting for Script Action" ),
     ("test", "This is just for testing", "1,2,3") `
    | ForEach-Object {[pscustomobject]@{kind = $_[0]; name = $_[1]; value 
= $_[2]}}

这很有效:

$myScriptObject

kind   name                     value                      
----   ----                     -----                      
status Selected Operation(s):   None                       
status Current Operation:       None                       
status Current Step:            Prompting for Script Action
test   This is just for testing 1,2,3 

...我什至可以这样做:

foreach($myObject in $myScriptObject) {
    if ($myObject.kind -eq 'status') {
        Write-Host $myObject.name $myObject.value
    }
}

输出这个:

Selected Operation(s): None
Current Operation: None
Current Step: Prompting for Script Action

我的问题是: 1. 如何在 $myScriptObject 中添加如下内容:

-kind "ActionMenuChoice" -Name "Do This" -Value 1
-kind "ActionMenuChoice" -Name "Do That" -Value 2
  1. 如何更改对象中已有的项目?

    status Current Step: Prompting for Script Action

到

status Current Step:            Prompting for Login

还是我做错了?这个想法来自于从函数返回大量变量的困难,我读到使用对象在函数中来回传递要好得多,发现使用对象更容易跟踪和在一定程度上操作。

干杯!

【问题讨论】:

  • 你似乎有一个对象数组。因此,要制作一个具有您问题 [1] 中的格式的文件,只需创建一个新对象并将其添加到数组中。 ///// 对于问题 [2] - 要更改数组中对象的属性,请使用 $Collection[$Index].PropertyName = 'New Value'。
  • 将自定义对象的 array 称为 object 令人困惑。请阐明添加类似... 的含义 - 您是否希望能够使用参数语法将新元素追加 到您的数组中?如果是这样,您将不得不编写一个函数。考虑使用由自定义对象的 .Name 属性作为键的哈希表,而不是数组,这样可以更轻松地更新现有对象。

标签: powershell object dynamic-arrays


【解决方案1】:

如果我们保留您当前的对象数组结构,您可以通过强制转换[collections.generic.list[object]] 将$myScriptObject 创建为通用列表类型。然后您可以使用.Add() 方法将项目添加到您的收藏中。

[collections.generic.list[object]]$myScriptObject = 
    @("status", "Selected Operation(s):", "None"), 
     ("status", "Current Operation:", "None"), 
     ("status", "Current Step:", "Prompting for Script Action" ),
     ("test", "This is just for testing", "1,2,3") |
        ForEach-Object {[pscustomobject]@{kind = $_[0]; name = $_[1]; value = $_[2]}}

[void]$myScriptObject.add([pscustomobject]@{"Kind" = "ActionMenuChoice"; "Name" = "Do This"; "Value" = 1})
[void]$myScriptObject.add([pscustomobject]@{"Kind" = "ActionMenuChoice"; "Name" = "Do That"; "Value" = 2})

如果您想更新该集合中的项目属性,您首先需要找到该集合中的对象/项目,然后访问您要更新的属性。

($myScriptObject | Where-Object {$_.name -eq 'Current Step:'}).value = "Prompting for Login"

Where-Object可以提供定位目标对象所需的条件。然后您可以使用object.property 语法来访问该属性。使用 PowerShell 对象,您可以使用直接赋值语法 (object.property = value) 来更新属性值。

【讨论】:

  • [ordered] 的东西如果您将散列表 立即 应用于 [PSCustomObject] 调用,则不需要。我会删除那些。 [grin] ///// arraylist 类型已弃用,取而代之的是 generic.list。另外,其中的第二个不会产生通常需要抑制的愚蠢的“做某事”输出。我也会改变这一点... [grin] ///// 对于 OP 所做的用例,没有明显的 reason 可以使用除 a标准数组...还是我又错过了什么?
  • @Lee_Dailey 我采纳了你的建议。
  • 酷!谢谢你……这让我感到不安,而不是真正的奥塔。 [咧嘴]
  • 简洁、优雅、中肯,谢谢!测试了你所有的解决方案,它很有魅力。如果我可以再一次对你施加好感,我有一个关于这一切的战略和战术问题。
  • 如果我可以再次强加给您,我将获得 Azure 对象,然后是一些 REST api 响应 - 从战略上讲,我是否应该将这两种其他类型的信息存储在一对单独的对象中,或将它们集中在 myScriptObject 中?这个战术是围绕从函数中取回我的对象​​-使用可怕的return $myScriptObject,简单地声明$myScriptObject,或者在调用函数时分配它,即$myScriptObject = Get-ScriptChoice($myScriptObject)
【解决方案2】:

我会改用数据表:

Add-Type -AssemblyName System.Collections

$dt = New-Object system.Data.DataTable
[void]$dt.Columns.Add('kind',[string]::empty.GetType() )
[void]$dt.Columns.Add('name',[string]::empty.GetType() )
[void]$dt.Columns.Add('value',[string]::empty.GetType() )


# Add new rows:
$newRow = $dt.NewRow()
$newRow.kind = 'status'
$newRow.name = 'Selected Operation(s):'
$newRow.value = 'None'

[void]$dt.Rows.Add( $newRow )

$newRow = $dt.NewRow()
$newRow.kind = 'status'
$newRow.name = 'Selected'
$newRow.value = 'None'

[void]$dt.Rows.Add( $newRow )


# Find row(s):
$rows = $dt.Select("kind = 'status'")
"Found:"
$dt

# Change first row by condition:
$rows = $dt.Select("kind = 'status'")
$rows[0].value = 'test'
[void]$dt.AcceptChanges()
"Changed one row:"
$dt

# Change all rows:
$rows = $dt.Select("")
$rows | % { $_.value = 'new' }
[void]$dt.AcceptChanges()
"Changed all:"
$dt

# Change all rows by condition:
$rows = $dt.Select("name = 'Selected'")
$rows | % { $_.value = 'newer' }
[void]$dt.AcceptChanges()
"Changed by condition:"
$dt

【讨论】:

    猜你喜欢
    • 2022-12-06
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 2016-10-08
    • 1970-01-01
    • 2014-10-24
    • 2022-10-05
    相关资源
    最近更新 更多