带哈希表的PowerShell数组

带哈希表的PowerShell数组,powershell,Powershell,我不确定我做错了什么,但是我需要一些代码方面的帮助。 我试图从一堆服务器上的一些文件中读取IP,然后将它们输出到屏幕上并导出到CSV。到目前为止,我已经写了这个 $Servers = @('server1', 'server2', 'server3') $export = @() foreach ($server in $Servers) { $filePath = "\\$server\d:\application\application.log" $ipsFailed = Get-Cont

我不确定我做错了什么,但是我需要一些代码方面的帮助。 我试图从一堆服务器上的一些文件中读取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}
我知道我的思路是正确的,因为运行below命令会返回我想要的结果,虽然这只适用于一台服务器,但如何将其放入哈希表中,以便在不影响输出的情况下为多台服务器工作?救命啊

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
  • 共享名内部不能有冒号
  • 将两个foreach的输出分配给一个收集所有输出的变量
  • 使用[PSCustomObject]

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

user6811411的答案是(实际上语法上是不正确的,它试图通过管道传输
foreach
循环的输出,但似乎有意这样做),创建一个非唯一对象流,每个对象只包含一个地址,然后过滤该流以消除任何重复。此方法将生成所需的输出(如果重写为语法正确),但除非您出于其他目的实际需要具有“ipsfiled”成员的对象数组,否则通过过滤字符串流来获取地址字符串数组更简单

$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
将产生的地址周围的引号(字符串子表达式)。此外,
selectstring
执行正则表达式匹配,并输出正则表达式
match
对象,因此需要
ToString
。将其全部合并到
ForEach对象中可能更有效。其他整理-不需要@()

最后,这是一个版本,通过使用参数、消除不必要的变量、不显示结果(仅导出文件)和看起来不像导出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

这样做行不通,因为您无法通过管道传输foreach循环的输出。在语法上,foreach(…){…}末尾的}是一个语句终止符,因此像
foreach($list中的项){$item}| Measure对象
这样的命令将解析为
foreach($list中的项){$item};|测量对象
,也就是说,它实际上是两个独立的命令,第二个命令没有输入。(需要PSv7吗?)除非foreach()被&{}包围,否则不能从foreach()进行管道传输。或者在下一行从$export导入。或者用()包围,将其转换为表达式(请参见我的答案)。我的评论旨在从作者那里得到一个修正,同时为新程序员提供“空管道元素”错误的合理解释。可能需要更改摘要行,而不是看到一个哈希表。如下所述,共享名中不能有“:”,但怀疑这只是一个抄写错误和(假设是)正在运行的版本有d$。$不需要加引号(带“-”),因为“”字符串中的变量替换只有在$后跟标识符时才会发生(即使它不存在,也可以是变量名),
$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
}
'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