添加列并为现有数组赋值

时间:2014-06-17 08:34:43

标签: arrays powershell csv

我想为从CSV生成的现有数组添加列和值。

这是我的代码:

$mycsv = "C:\Users\test\Documents\serveurs.csv"
$servers = Import-Csv $mycsv

结果如下:

ServerName                              Ip
----------                              --
Castor                                  172.22.0.64
Pollux                                  172.22.0.67

我想为每个ServerName添加带有值的新列,如下所示:

ServerName                              Ip                  Available
----------                              --                  ---------
Castor                                  172.22.0.64         Yes
Pollux                                  172.22.0.67         No

我尝试了以下代码:

$item = New-Object PSObject
$item | Add-Member -Type NoteProperty -Name 'Available' -Value 'Yes'

$servers += $item

但它实际上不起作用,任何人都可以帮助我吗?

最后的想法是使用Test-Connection cmdlet在服务器可通过网络访问时分配值。

4 个答案:

答案 0 :(得分:6)

您可以使用计算属性来确定每台服务器的可用性:

$csv1 = 'C:\Users\test\Documents\serveurs.csv'
$csv2 = 'C:\Users\test\Documents\serveurs2.csv'

Import-Csv $csv1 |
    Select-Object ServerName, Ip,
        @{n='Available';e={[bool](Test-Connection -Count 1 $_.Ip 2>$null)}} |
    Export-Csv $csv2 -NoType

但是,请注意,即使将测试限制为每个服务器的单个探测器,也可能需要一些时间,因为所有项目都是按顺序处理的。如果要测试很多服务器,则可能需要将检查作为并行作业运行:

$csv = 'C:\Users\test\Documents\serveurs.csv'

$servers = Import-Csv $csv

# clear job queue
Remove-Job *
# load job queue with test jobs
$servers | ForEach-Object {
    Start-Job -ScriptBlock {
        $args[0]
        [bool](Test-Connection -Count 1 $args[0] 2>$null)
    } -ArgumentList $_.Ip
}
# wait for jobs to finish
do {
    Start-Sleep -Milliseconds 100
} while (Get-Job -State 'Running')

# gather job results into hashtable
$availability = @{}
Get-Job | ForEach-Object {
    $result = Receive-Job -Id $_.Id
    $availability[$result[0]] = $result[1]
    Remove-Job -Id $_.Id
}

# add availability column to server data and export back to CSV
$servers |
    Select-Object ServerName, Ip, @{n='Available';e={$availability[$_.Ip]}} |
    Export-Csv $csv -NoType

答案 1 :(得分:2)

我不确定是否存在用于操作CSV文件的内置模块。

您可以操纵CSV文件为您提供输出或将NoteProperty添加到现有变量。

示例1:

(cat "C:\Users\test\Documents\serveurs.csv") -replace "Servername;IP", "Servername;IP;Available" -replace "64","64;" -replace "67","67;" | out-file "C:\Users\test\Documents\serveurs.csv"

示例2:

$CSV | Add-Member -MemberType NoteProperty "Available" -Value "Yes"

我想这应该能满足你的需求。

编辑:

自问题澄清以来,这是建议的答案。

我很确定存在一种更简单的方法来实现这一点,但无论如何都可以使用

$CSV | Add-Member -MemberType NoteProperty "Available" -Value "" 
for ($i=0; $i -le $CSV.Length-1; $i++) {$CSV[$i].Available = Test-Connection $CSV[$i].Servername -quiet}

答案 2 :(得分:2)

除了填充字段值之外,添加属性的另一个选项是使用Select-Object。

$csv = 'C:\Users\test\Documents\serveurs.csv'
$servers = Import-Csv $csv | select *,Availability

然后根据您的选择填充可用性。

如果您要使用后台作业进行多线程,我认为您最好将服务器名称分组并设置后台作业以处理每个组。设置和拆除后台作业大约需要5秒钟,将它们用于ping一台计算机等琐碎任务可能会适得其反。

编写代码需要做更多工作,但如果你想要多线程,我认为运行空间池会比这个应用程序中的后台作业产生更快的结果。

答案 3 :(得分:0)

如果要创建自定义对象并添加值,可以通过执行以下操作来实现:

     [System.Collections.ArrayList]$myList = @()
     $mycsv = "C:\Users\test\Documents\serveurs.csv"
     $servers = Import-Csv $mycsv
     ForEach ( $server in $servers ) {
     $myobj = New-Object PSObject
     $test="No"
     if (Test-Connection $server.ip -Count 1 | Out-Null){
     $test="Yes"
     } 
     Add-Member -InputObject $myobj -NotePropertyName Name -NotePropertyValue $server.ServerName
     Add-Member -InputObject $myobj -NotePropertyName IP -NotePropertyValue $server.ip
     Add-Member -InputObject $myobj -NotePropertyName Available -NotePropertyValue $test
     $mylist.add($myobj)
     }$mylist

您将收到对象列表,然后可以将其导出到csv或sort或其他任何内容