我想逐行打印自定义对象中的所有项目。我使用的陈述是:
TestObject ([PSCustomObject]@{item1=1 ;item2=2; item3=3},[PSCustomObject]@{item1=4;item2=5;item3=6}) -Verbose
我的功能定义如下:
function TestObject
{
[CmdLetBinding()]
Param(
[parameter(Mandatory=$True]
[object[]]$objectNames
)
Begin{}
Process
{
foreach ($object in $objectNames)
{
$myItems =@()
$myItems += $object
foreach ($o in $myItems.GetEnumerator())
{
Write-Verbose "---------------$o--------------"
foreach ($i in $o)
{
Write-Verbose "Name:$i.Key Value:$i.Value"
}
}
Write-Verbose "$object"
}
}
End{}
}
我预计输出如下:
VERBOSE: ---------------@{item1=1; item2=2; item3=3}--------------
VERBOSE: Name:item1 Value:1
VERBOSE: Name:item2 Value:2
VERBOSE: Name:item3 Value:3
VERBOSE: @{item1=1; item2=2; item3=3}
VERBOSE: ---------------@{item1=4; item2=5; item3=6}--------------
VERBOSE: Name:item1 Value:4
VERBOSE: Name:item2 Value:5
VERBOSE: Name:item3 Value:6
VERBOSE: @{item1=4; item2=5; item3=6}
相反,我得到了这个结果:
如果我知道自定义对象的格式是由分号分隔的对(键,值)的集合,我该如何拆分自定义对象中的项?
答案 0 :(得分:5)
你混淆了哈希表和自定义对象。仅仅因为你可以从另一个创建一个并不意味着它们的行为相同。 Hashtables可以通过GetEnumerator()
进行枚举,生成DictionaryEntry
个Key
和Value
个属性的对象列表。
PS C:\> $ht = @{item1=1 ;item2=2; item3=3} PS C:\> $ht Name Value ---- ----- item2 2 item3 3 item1 1 PS C:\> "$ht" System.Collections.Hashtable PS C:\> $ht.GetType().FullName System.Collections.Hashtable PS C:\> $ht.GetEnumerator() | % { $_.GetType().FullName } System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry PS C:\> $ht.GetEnumerator() | % { '{0} = {1}' -f $_.Key, $_.Value } item2 = 2 item3 = 3 item1 = 1
当您将哈希表转换为自定义对象时,它将停止为哈希表(即使其字符串表示仍然看起来像哈希表),并且不再表现得像哈希表:
PS C:\> $o = [PSCustomObject]$ht PS C:\> $o item2 item3 item1 ----- ----- ----- 2 3 1 PS C:\> "$o" @{item2=2; item3=3; item1=1} PS C:\> $o.GetType().FullName System.Management.Automation.PSCustomObject PS C:\> $o.GetEnumerator() Method invocation failed because [System.Management.Automation.PSCustomObject] does not contain a method named 'GetEnumerator'. At line:1 char:1 + $o.GetEnumerator() + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (GetEnumerator:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound
要枚举对象的属性,请使用其内在属性:
PS C:\> $o.PSObject.Properties MemberType : NoteProperty IsSettable : True IsGettable : True Value : 2 TypeNameOfValue : System.Int32 Name : item2 IsInstance : True MemberType : NoteProperty IsSettable : True IsGettable : True Value : 3 TypeNameOfValue : System.Int32 Name : item3 IsInstance : True MemberType : NoteProperty IsSettable : True IsGettable : True Value : 1 TypeNameOfValue : System.Int32 Name : item1 IsInstance : True PS C:\> $o.PSObject.Properties | % { '{0} = {1}' -f $_.Name, $_.Value } item2 = 2 item3 = 3 item1 = 1
至于为什么输出字符串看起来不像你期望的那样:PowerShell不会在字符串中进行复杂的变量扩展。 "$i.Value"
扩展为$i
的字符串表示形式,后跟字符串".Value"
。如果您想要字符串中对象的属性,则需要使用字符串连接:
"Name: " + $i.Name + ", Value: " + $i.Value
子表达式:
"Name: $($i.Name), Value: $($i.Value)"
或格式运算符:
"Name: {0}, Value: {1}" -f $i.Name, $i.Value
将您的功能简化为以下内容:
function Test-Object {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[array]$ObjectNames
)
foreach ($o in $ObjectNames) {
foreach ($i in $o.PSObject.Properties) {
Write-Verbose "Name: $($i.Name), Value: $($i.Value)"
}
}
}
它应该做你期望的。