在PowerShell中迭代PSObject属性

时间:2016-06-07 20:27:19

标签: powershell

我有这个PSObject(来自XML):

bool : {IsActive, ShowOnB2C, ShowOnB2B, IsWebNews}
str  : {id, ProductId, GroupName, Unit...}
int  : {ProductIdNumeric, Prices_SalesOne, Prices_Treater, Prices_B2C...}
arr  : {EnvironmentBrands, Catalogs, NavisionLevels}
long : long

我想在不使用属性名称的情况下迭代属性,例如bool

我试图像这样索引对象:

$document[0]

但这没有给我什么,但它也不会导致任何错误。

Select-Object有点作品,但后来我必须使用属性名称,我不想要它。

$documents | Select-Object bool,str

ForEach不会迭代属性。

$documents | ForEach {
    $_.name
}

返回doc,这是包含bools,int和字符串的标记(XML)的名称。

5 个答案:

答案 0 :(得分:39)

可以使用隐藏属性PSObject

$documents.PSObject.Properties | ForEach-Object {
    $_.Name
    $_.Value
}

答案 1 :(得分:6)

我更喜欢使用foreach来遍历PowerShell对象:

foreach($object_properties in $obj.PsObject.Properties)
{
    # Access the name of the property
    $object_properties.Name

    # Access the value of the property
    $object_properties.Value
}

通常,foreach的效果高于Foreach-Object

是的,foreach实际上与Foreach-Object不同。

答案 2 :(得分:3)

stej mentioned一样,您可以使用Get-Member cmdlet,其中包含-MemberType参数:

$documents | Get-Member -MemberType Property | ForEach-Object {
    $_.Name
}

答案 3 :(得分:3)

Get-Member也可能需要NoteProperty。

movmskps

答案 4 :(得分:0)

我使用以下命令枚举属性并将它们放在表中:

$Object.PSObject.Properties | Format-Table @{ Label = 'Type'; Expression = { "[$($($_.TypeNameOfValue).Split('.')[-1])]" } }, Name, Value -AutoSize -Wrap

我为此编写了以下函数,该函数还迭代了嵌套属性。

function Enumerate-ObjectProperties {
    param (
        [psobject] $Object,
        [string] $Root
    )

    Write-Output $($Object.PSObject.Properties | Format-Table @{ Label = 'Type'; Expression = { "[$($($_.TypeNameOfValue).Split('.')[-1])]" } }, Name, Value -AutoSize -Wrap | Out-String)

    foreach ($Property in $Object.PSObject.Properties) {
        # Strings always have a single property "Length". Do not enumerate this.
        if (($Property.TypeNameOfValue -ne 'System.String') -and ($($Object.$($Property.Name).PSObject.Properties))) {
            $NewRoot = $($($Root + '.' + $($Property.Name)).Trim('.'))
            Write-Output "Property: $($NewRoot)"
            Enumerate-ObjectProperties -Object $($Object.$($Property.Name)) -Root $NewRoot
        }
    }
}

Enumerate-ObjectProperties $YourObject

但是请记住,某些对象的构造有些典型,因为它们在嵌套中具有“循环”。引用父对象的子属性。 一个例子是:

Get-Date 'somebogusdata'
Enumerate-ObjectProperties $Error[0]

这将创建一个循环。 您当然可以添加“ depth”参数来添加深度计数器,从而指定您只想进入某个深度。 看起来像这样:

$script:Level = 1
function Enumerate-ObjectProperties {
    param (
        [psobject] $Object,
        [int32] $Depth = 1,
        [string] $Root
    )

    Write-Output $($Object.PSObject.Properties | Format-Table @{ Label = 'Type'; Expression = { "[$($($_.TypeNameOfValue).Split('.')[-1])]" } }, Name, Value -AutoSize -Wrap | Out-String)

    foreach ($Property in $Object.PSObject.Properties) {
        # Strings always have a single property "Length". Do not enumerate this.
        if (($Property.TypeNameOfValue -ne 'System.String') -and ($($Object.$($Property.Name).PSObject.Properties)) -and ($Level -le $Depth)) {
            $NewRoot = $($($Root + '.' + $($Property.Name)).Trim('.'))
            $Level++
            Write-Output "Property: $($NewRoot) (Level: $Level)"
            Enumerate-ObjectProperties -Object $($Object.$($Property.Name)) -Root $NewRoot
            $Level--
        }
    }
}

Enumerate-ObjectProperties -Object $Error[0] -Depth 2