向现有数组添加列并赋值

7

我想在从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 命令来确定服务器是否可以通过网络访问,并分配相应的值。

4个回答

9
您可以使用计算属性来确定每个服务器的可用性:
$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

比我的答案好多了,我需要仔细研究这个脚本,学习更多关于哈希表和结构的知识。你能解释一下“e=”子句是什么吗?(在e={$availability[$_.Ip])中)它只是从脚本表达式中获取值,对吗? - AlexPawlak
@Koliat 请查看计算属性的 TechNet 文章。这里的 eExpression 的简称。 - Ansgar Wiechers

5

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

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

然后您可以按照所需的方式填写可用性。如果您要使用后台作业进行多线程处理,我认为最好将服务器名称分组并设置一个后台作业来处理每个组。设置和拆除后台作业大约需要5秒钟的时间,对于像ping单个计算机这样的琐碎任务使用它们可能会适得其反。虽然编码更加复杂,但如果想要多线程处理,我认为运行空间池在此应用程序中可产生更快的结果,胜过后台作业。

3

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

你可以通过操作CSV文件得到输出,也可以在现有变量中添加NoteProperty。

例如:

(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}

你的第二个例子是可以工作的,但它并不是我想要的。因为它实际上将“yes”这个值分配给了我的所有ServerName。 - Adeel ASIF
很抱歉,您没有明确指定您想要的确切内容。您是否希望根据服务器在网络上的可达性来分配值? - AlexPawlak
是的,我将使用Test-connection cmdlet。我知道如何使用它,但我想将最终结果放入我的数组中(从我的csv生成)。我的问题是“如何为从csv生成的数组分配新列和新值?”谢谢你的帮助。 - Adeel ASIF
已更新并附上答案。 - AlexPawlak

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文件或按任何方式进行排序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接