Powershell - 自定义对象中的多个值
Powershell - multiple values in custom object
我一直在编写一个脚本,它将采用 IPs/DNSes 并创建一个 2 列输出。当它在 powershell 内部工作时,一旦我尝试将其导出为 CSV,它 return system.object。我该如何解决?这是我的代码:
function Resolve-IPDNS {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$IPDNS,
[string]$DNSServer = "1.1.1.1"
)#param
BEGIN {}
Process {
foreach ($addrs in $IPDNS ) {
#Resolve IP or DNS
IF ($addrs -as [ipaddress]) {
$resolve_params = @{'Name' = $addrs
'Server' = $DNSServer
'Type' = 'PTR'}
} ELSE {
$resolve_params = @{'Name' = $addrs
'Server' = $DNSServer
'Type' = 'A'}
}
$resolve = Resolve-DnsName @resolve_params
#Create props
IF ($addrs -as [ipaddress]) {
$props = @{'IP' = $resolve.Name
'DNS' = $resolve.NameHost}
} ELSE {
$props = @{'IP' = $resolve.IPAddress
'DNS' = $resolve.Name}
}#IF
#Output data
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
}#foreach
}#Process
END {}
}#function
Resolve-IPDNS
所以如果尝试提供 bbc.com 我得到结果:
IP DNS
-- ---
{151.101.0.81, 151.101.64.81, 151.101.128.81, 151.101.192.81} {bbc.com, bbc.com, bbc.com, bbc.com}
有没有办法 expand/unwrap 同时保持对象方式?
确保迭代 每个 来自 Resolve-DnsName
:
的结果
function Resolve-IPDNS {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$IPDNS,
[string]$DNSServer = "1.1.1.1"
)
Process {
foreach($addrs in $IPDNS) {
if($addrs -as [ipaddress]) {
$resolve_params = @{
'Name' = $addrs
'Server' = $DNSServer
'Type' = 'PTR'
}
}
else {
$resolve_params = @{
'Name' = $addrs
'Server' = $DNSServer
'Type' = 'A'
}
}
foreach($resolve in Resolve-DnsName @resolve_params) {
if($addrs -as [ipaddress]) {
$props = @{
'IP' = $resolve.Name
'DNS' = $resolve.NameHost
}
}
else {
$props = @{
'IP' = $resolve.IPAddress
'DNS' = $resolve.Name
}
}
#Output data
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
}
}
}
}
这里的问题是名称解析可以 return 多个结果。这正是您的示例所发生的情况,bbc.com
。
您的代码没有对结果做任何特殊处理,因此对象的 "column"(实际上是 属性)本身就是一个数组。您可以通过屏幕上看到的结果看到这一点;它呈现为由 { }
.
包围的逗号分隔列表
当您导出到 CSV 时,每个 属性 都会调用其 .ToString()
方法,在标准 PowerShell 数组上,它将为您提供 System.Object[]
的确切结果,这可以看到如下:
@(1,2,3).ToString()
所以,你需要做出选择:
- 将数组 存储在对象中 作为预呈现的字符串,因为您希望它出现在 CSV 中(从而丢失原始数组类型)
- 将数组作为存储,在导出之前进行字符串渲染
- 向执行转换或导出的对象添加辅助方法
-join
运算符在这里会很好,因为即使值不是数组,它也能正常工作。
对于第一个选项,您可以在分配时轻松处理它:
@{
'IP' = $resolve.Name -join '+'
'DNS' = $resolve.NameHost -join '+'
}
对于第二个选项,在管道中即时更改您的值:
Resolve-IPDNS -IPDNS 'bbc.com' |
ForEach-Object -Process {
New-Object -TypeName PSObject -Property @{
'IP' = $_.IP -join '+'
'DNS' = $_.DNS -join '+'
}
} |
Export-Csv MyCsv.csv -NoTypeInformation
对于第三个选项,请考虑:
$obj = New-Object -TypeName psobject -Property $props |
Add-Member -MemberType ScriptMethod -Name JoinedClone -Value {
New-Object -TypeName PSObject -Property @{ param([String]$JoinString
'IP' = $this.IP -join $JoinString
'DNS' = $this.DNS -join $JoinString
}
}
然后,您可以执行以下操作:
(Resolve-IPDNS -IPDNS 'bbc.com').JoinedClone() | Export-Csv MyCsv.csv -NoTypeInformation
我一直在编写一个脚本,它将采用 IPs/DNSes 并创建一个 2 列输出。当它在 powershell 内部工作时,一旦我尝试将其导出为 CSV,它 return system.object。我该如何解决?这是我的代码:
function Resolve-IPDNS {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$IPDNS,
[string]$DNSServer = "1.1.1.1"
)#param
BEGIN {}
Process {
foreach ($addrs in $IPDNS ) {
#Resolve IP or DNS
IF ($addrs -as [ipaddress]) {
$resolve_params = @{'Name' = $addrs
'Server' = $DNSServer
'Type' = 'PTR'}
} ELSE {
$resolve_params = @{'Name' = $addrs
'Server' = $DNSServer
'Type' = 'A'}
}
$resolve = Resolve-DnsName @resolve_params
#Create props
IF ($addrs -as [ipaddress]) {
$props = @{'IP' = $resolve.Name
'DNS' = $resolve.NameHost}
} ELSE {
$props = @{'IP' = $resolve.IPAddress
'DNS' = $resolve.Name}
}#IF
#Output data
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
}#foreach
}#Process
END {}
}#function
Resolve-IPDNS
所以如果尝试提供 bbc.com 我得到结果:
IP DNS
-- ---
{151.101.0.81, 151.101.64.81, 151.101.128.81, 151.101.192.81} {bbc.com, bbc.com, bbc.com, bbc.com}
有没有办法 expand/unwrap 同时保持对象方式?
确保迭代 每个 来自 Resolve-DnsName
:
function Resolve-IPDNS {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$IPDNS,
[string]$DNSServer = "1.1.1.1"
)
Process {
foreach($addrs in $IPDNS) {
if($addrs -as [ipaddress]) {
$resolve_params = @{
'Name' = $addrs
'Server' = $DNSServer
'Type' = 'PTR'
}
}
else {
$resolve_params = @{
'Name' = $addrs
'Server' = $DNSServer
'Type' = 'A'
}
}
foreach($resolve in Resolve-DnsName @resolve_params) {
if($addrs -as [ipaddress]) {
$props = @{
'IP' = $resolve.Name
'DNS' = $resolve.NameHost
}
}
else {
$props = @{
'IP' = $resolve.IPAddress
'DNS' = $resolve.Name
}
}
#Output data
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
}
}
}
}
这里的问题是名称解析可以 return 多个结果。这正是您的示例所发生的情况,bbc.com
。
您的代码没有对结果做任何特殊处理,因此对象的 "column"(实际上是 属性)本身就是一个数组。您可以通过屏幕上看到的结果看到这一点;它呈现为由 { }
.
当您导出到 CSV 时,每个 属性 都会调用其 .ToString()
方法,在标准 PowerShell 数组上,它将为您提供 System.Object[]
的确切结果,这可以看到如下:
@(1,2,3).ToString()
所以,你需要做出选择:
- 将数组 存储在对象中 作为预呈现的字符串,因为您希望它出现在 CSV 中(从而丢失原始数组类型)
- 将数组作为存储,在导出之前进行字符串渲染
- 向执行转换或导出的对象添加辅助方法
-join
运算符在这里会很好,因为即使值不是数组,它也能正常工作。
对于第一个选项,您可以在分配时轻松处理它:
@{
'IP' = $resolve.Name -join '+'
'DNS' = $resolve.NameHost -join '+'
}
对于第二个选项,在管道中即时更改您的值:
Resolve-IPDNS -IPDNS 'bbc.com' |
ForEach-Object -Process {
New-Object -TypeName PSObject -Property @{
'IP' = $_.IP -join '+'
'DNS' = $_.DNS -join '+'
}
} |
Export-Csv MyCsv.csv -NoTypeInformation
对于第三个选项,请考虑:
$obj = New-Object -TypeName psobject -Property $props |
Add-Member -MemberType ScriptMethod -Name JoinedClone -Value {
New-Object -TypeName PSObject -Property @{ param([String]$JoinString
'IP' = $this.IP -join $JoinString
'DNS' = $this.DNS -join $JoinString
}
}
然后,您可以执行以下操作:
(Resolve-IPDNS -IPDNS 'bbc.com').JoinedClone() | Export-Csv MyCsv.csv -NoTypeInformation