具有哈希表的PowerShell数组

时间:2019-07-08 06:09:11

标签: powershell

我不确定自己在做什么错,但是我需要一些有关此代码的帮助。 我正在尝试从一堆服务器上的某些文件中读取IP,然后将其输出到屏幕上并导出为CSV。到目前为止,我已经写了这个。

$Servers = @('server1', 'server2', 'server3')
$export = @()
foreach ($server in $Servers) {

$filePath = "\\$server\d:\application\application.log"
$ipsFailed = Get-Content $filePath | Select-String "Could not resolve" | ForEach-Object {($_.tostring()).split()[-1]} | Select-Object -Unique
$export += New-Object psobject -Property @{
    ipsFailed = $ipsFailed
    }

$export
$exportFile| Export-Csv "ipsFailed.csv" -NoTypeInformation
}

当我运行此代码(不导出)时,我在屏幕上看到了它,这不是我想要的。我想要更多的线性表而不是此数组?不用说出口是没有用的。

ipsFailed                     
-------------                     
{192.168.141.161, 192.168.141.162}
{192.168.141.161, 192.168.141.162}
{192.168.141.160, 192.168.141.162}

我知道我走对了,因为在命令下运行将返回我想要的内容,尽管这仅适用于1台服务器,但是如何将其放入哈希表以用于多台服务器而又不会增加输出?帮助。

PS C:\> Get-Content $filePath | Select-String "Could not resolve" | ForEach-Object {($_.tostring()).split()[-1]} | Select-Object -Unique
192.168.141.160
192.168.141.162

2 个答案:

答案 0 :(得分:0)

  • 共享名称中不能包含冒号
  • 将两个foreach的输出分配给一个收集所有输出的变量
  • 使用[PSCustomObject]
$Servers = @('server1', 'server2', 'server3')

$export = foreach ($server in $Servers) {
    $filePath = "\\$server\d`$\application\application.log"
    Get-Content $filePath | Select-String -Pattern "Could not resolve"| ForEach-Object{
        [PSCustomObject]@{
           ipsFailed = ($_ -split ' ')[-1]
        }
    }
} | Select-Object ipsFailed -Unique
$export
$export | Export-Csv "ipsFailed.csv" -NoTypeInformation

答案 1 :(得分:0)

原始代码的问题在于,每个服务器的结果是(字符串)唯一IPv4地址的数组,然后将其分配给psobject的单个成员。然后,将此(单个)对象附加到数组$export上,从而创建一个数组数组(显示时看起来像样本输出)。它也具有重复的地址,因为在消除重复时,每个服务器都将被单独处理。

user6811411的回答是(实际上是语法上不正确的,通过尝试传递foreach循环的输出,但似乎打算这样做)创建了一个非唯一对象流,每个对象仅包含一个地址,然后进行过滤流以消除任何重复。此方法将产生所需的输出(如果在语法上被重写为正确的格式),但除非您实际上出于其他目的而希望使用带有“ ipsFailed”成员的对象数组,否则通过过滤流可以更简单地获取地址字符串数组字符串

$Servers = @('server1', 'server2', 'server3')
$export = (foreach ($server in $Servers) {

  $filePath = "\\$server\d`$\application\application.log"

  Get-Content $filePath |
    Select-String "Could not resolve" |
    ForEach-Object {($_.tostring()).split()[-1]}

}) | Select-Object -Unique

$export
$export | Set-Content "ipsFailed.csv"
}

注意:在foreach循环中放置(),可将其变为表达式而不是语句。另外,Export-Csv对于一个成员对象来说有点多余,现在我们甚至都没有,所以可以使用Set-Content轻松创建地址文件。这看起来与所需输出样本完全一样。如果需要Export-Csv输出,则需要一点点摆弄,添加“列标头”(设置+添加内容)和Export-Csv会产生的地址周围的引号(字符串子表达式)。此外,Select-String执行正则表达式匹配并输出正则表达式Match对象,因此需要ToString。将它们全部合并到ForEach-Object中可能会更有效。其他整理-不需要@()。

$Servers = 'server1', 'server2', 'server3'
$export = (foreach ($server in $Servers) {

  $filePath = "\\$server\d`$\application\application.log"

  Get-Content $filePath |
    ForEach-Object {
      if ($_ -match 'Could not resolve.*?([^ ]*)$') {
        """$($matches[1])"""
      }
    }
}) | Select-Object -Unique

$export
Set-Content ipsFailed.csv '"ipsFailed"'
$export | Add-Content ipsFailed.csv
}

最后,这是一个通过使用参数,消除不必要的变量,不显示结果(仅导出文件)并且看起来不像Export-Csv的命令最少的版本。

'server1', 'server2', 'server3' |
  ForEach-Object {
    Select-String -Pattern 'Could not resolve.*?([^ ]*)$' -LiteralPath "\\$_\d`$\application\application.log" |
      ForEach-Object { $_.matches[0].groups[1].value }
  } | Select-Object -Unique | Set-Content ipsFailed.csv