首先,由于这引出了我的问题,我将首先注意到我在PowerShell中使用了XML,并且喜欢如何将XML文件中的数据快速地读取到自定义对象的数组中。例如,如果我有以下XML文件:
<stuff>
<item name="Joe" age="32">
<info>something about him</info>
</item>
<item name="Sue" age="29">
<info>something about her</info>
</item>
<item name="Cat" age="12">
<info>something else</info>
</item>
</stuff>
如果我简单地阅读它,就像这样:
[xml]$myxml = Get-Content .\my.xml
然后我可以得到这样的项目数组:
[array]$myitems = $myxml.stuff.Item
$myitems
name age info
---- --- ----
Joe 32 something about him
Sue 29 something about her
Cat 12 something else
所以,现在我的问题是:
如何创建自定义对象数组的类似结构,并在我的脚本中初始化它们,而不用读取文件?
我可以做很多循环和/或大量创建/初始化单个对象,然后一次添加一个数组......
但似乎应该有一种方法以更简单的方式执行此创建/初始化。请注意,这里的关键是我的自定义对象有两个以上的元素(否则,我已经使用了哈希)。
我甚至考虑过创建一个大的XML字符串,并使用Select-XML,但我无法正确理解语法(如果这是正确的方向,那就是正确的方向)。
答案 0 :(得分:60)
我会沿着这些方向做点什么:
$myitems =
@([pscustomobject]@{name="Joe";age=32;info="something about him"},
[pscustomobject]@{name="Sue";age=29;info="something about her"},
[pscustomobject]@{name="Cat";age=12;info="something else"})
请注意,这仅适用于 PowerShell 3 ,但由于您未在问题中提及该版本,因此我认为这对您无关紧要。
<强>更新强>
评论中提到过,如果您执行以下操作:
$younger = $myitems | Where-Object { $_.age -lt 20 }
Write-Host "people younger than 20: $($younger.Length)"
您不会像预期的那样得到1
。返回单个pscustomobject
时会发生这种情况。现在这对于PowerShell中的大多数其他对象来说不是问题,因为它们具有Length
和Count
的代理属性。不幸的是pscustomobject
没有。这在Powershell 6.1.0中得到修复。您可以使用运算符@()
来解决此问题:
$younger = @($myitems | Where-Object { $_.age -lt 20 })
答案 1 :(得分:25)
这是在PowerShell中初始化自定义对象数组的简明方法。
> $body = @( @{ Prop1="1"; Prop2="2"; Prop3="3" }, @{ Prop1="1"; Prop2="2"; Prop3="3" } )
> $body
Name Value
---- -----
Prop2 2
Prop1 1
Prop3 3
Prop2 2
Prop1 1
Prop3 3
答案 2 :(得分:21)
也许你的意思是这样的?我喜欢创建一个对象并使用Format-Table:
PS C:\Users\Joel> $array = @()
PS C:\Users\Joel> $object = New-Object -TypeName PSObject
PS C:\Users\Joel> $object | Add-Member -Name 'Name' -MemberType Noteproperty -Value 'Joe'
PS C:\Users\Joel> $object | Add-Member -Name 'Age' -MemberType Noteproperty -Value 32
PS C:\Users\Joel> $object | Add-Member -Name 'Info' -MemberType Noteproperty -Value 'something about him'
PS C:\Users\Joel> $array += $object
PS C:\Users\Joel> $array | Format-Table
Name Age Info
---- --- ----
Joe 32 something about him
这将根据属性将数组中的所有对象放在列中。
提示:使用-auto
更好地调整表格
PS C:\Users\Joel> $array | Format-Table -Auto
Name Age Info
---- --- ----
Joe 32 something about him
您还可以在表格中指定所需的属性。只需用逗号分隔每个属性名称:
PS C:\Users\Joel> $array | Format-Table Name, Age -Auto
Name Age
---- ---
Joe 32
答案 3 :(得分:9)
这是一个更简洁的接受答案的版本,它避免重复NoteProperty标识符和[pscustomobject]
- cast:
$myItems = ("Joe",32,"something about him"), ("Sue",29,"something about her")
| ForEach-Object {[pscustomobject]@{name = $_[0]; age = $_[1]; info = $_[2]}}
结果:
> $myItems
name age info
---- --- ----
Joe 32 something about him
Sue 29 something about her
答案 4 :(得分:8)
初始化数组的最简单方法
创建数组
$array = @()
创建标题
$line = "" | select name,age,phone
填写
$line.name = "Leandro"
$line.age = "39"
$line.phone = "555-555555"
将行添加到$ array
$array += $line
<强>结果强>
$array
name age phone
---- --- -----
Leandro 39 555-555555
答案 5 :(得分:1)
使用&#34; Here-String&#34;并转换为XML。
[xml]$myxml = @"
<stuff>
<item name="Joe" age="32">
<info>something about him</info>
</item>
<item name="Sue" age="29">
<info>something about her</info>
</item>
<item name="Cat" age="12">
<info>something else</info>
</item>
</stuff>
"@
[array]$myitems = $myxml.stuff.Item
$myitems
答案 6 :(得分:0)
我必须创建一个预定义类型的数组,并且我成功地执行了以下操作:
{{1}}
答案 7 :(得分:0)
鉴于上述数据,这就是我的处理方式:
# initialize the array
[PsObject[]]$people = @()
# populate the array with each object
$people += [PsObject]@{ Name = "Joe"; Age = 32; Info = "something about him" }
$people += [PsObject]@{ Name = "Sue"; Age = 29; Info = "something about her" }
$people += [PsObject]@{ Name = "Cat"; Age = 12; Info = "something else" }
即使您在Where-Object
之后只有1个项目,以下代码也可以使用:
# display all people
Write-Host "People:"
foreach($person in $people) {
Write-Host " - Name: '$($person.Name)', Age: $($person.Age), Info: '$($person.Info)'"
}
# display with just 1 person (length will be empty if using 'PSCustomObject', so you have to wrap any results in a '@()' as described by Andrew Savinykh in his updated answer)
$youngerPeople = $people | Where-Object { $_.Age -lt 20 }
Write-Host "People younger than 20: $($youngerPeople.Length)"
foreach($youngerPerson in $youngerPeople) {
Write-Host " - Name: '$($youngerPerson.Name)'"
}
结果:
People:
- Name: 'Joe', Age: 32, Info: 'something about him'
- Name: 'Sue', Age: 29, Info: 'something about her'
- Name: 'Cat', Age: 12, Info: 'something else'
People younger than 20: 1
- Name: 'Cat'
答案 8 :(得分:0)
关于班级的一些变化。用哈希表对其进行初始化。
class Point { $x; $y }
$a = [Point[]] (@{ x=1; y=2 },@{ x=3; y=4 })
$a
x y
- -
1 2
3 4
$a.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Point[] System.Array
$a[0].gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False Point System.Object