好的,所以我有这个数组,它基本上是一个CSV文件的Import-Csv
。数组中的每个对象都是整个CSV行。当我用Excel打开它时,输入文件正确呈现(列是正确的)
此CSV文件以逗号分隔,格式如下:
“first”,“second”,“这就是全部
第三个
列”, “第四”
我已经让我的脚本中的所有内容都能正常工作,除了我需要将这个数组写入.csv文件的部分,其格式将正确呈现。我使用Out-File
,Export-Csv
时遇到了问题,我甚至试过了this,但它并没有完全满足我的需求。每个对象都需要是csv文件中的新行,只出现一次,并且必须遵循Excel对CSV文件的呈现(即每列需要双引号和逗号分隔)。
我甚至非常绝望,我正试图通过这样做正确地手动格式化这个东西:
$Array | % { $_ -replace "`"@`{","`n`"" } | % { $_ -replace "}`"","`"`n" } | % { $_ -replace "`;","`"`;`"" } | % { $_ -replace "Plugin ID=","" } | % { $_ -replace "CVE=","" } | % { $_ -replace "CVSS=","" } | % { $_ -replace "Risk=","" } | % { $_ -replace "Host=","" } | % { $_ -replace "Protocol=","" } | % { $_ -replace "Port=","" } | % { $_ -replace "Name=","" } | % { $_ -replace "Synopsis=","" } | % { $_ -replace "Solution=","" } | % { $_ -replace "Description=","" } | % { $_ -replace "Plugin Output=","" } | % { $_ -replace "`";`"","`",`"" } | Out-File "$dirResults\$Results-$Time.csv"
基本上,我在这里做的是几件事:
以下是一段代码:
$arrayHeader = @("Plugin ID;CVE;CVSS;Risk;Host;Protocol;Port;Name;Synopsis;Description;Solution;Plugin Output")
$OutterArrayException = Import-Csv "$dirExceptions\$FileException" -Delimiter ","
$InnerArrayScanMe = New-Object System.Collections.ArrayList
# This method keeps the arrays separate types
FOREACH ( $Object in $OutterArrayScanMe )
{ $InnerArrayScanMe.Add("$Object") | Out-Null }
# Note that the OutterArrayException is an Import-Csv from a similarly formatted file as OutterArrayScanMe
FOREACH ( $Exception in $OutterArrayException )
{ $InnerArrayScanMe.Remove("$Exception") }
# This method keeps the arrays separate types
$OutterArrayScanMe = @($arrayHeader) + @($InnerArrayScanMe)
$OutterArrayScanMe | Export-Csv "$dirResults\$FileScanMe-$startTime.csv" -Delimiter ";" -NoTypeInformation
更新:
当我使用export-csv时,对象的新行将信息作为新行放在csv中。因此,应该看起来像这样的东西变得非常混乱。
UPDATE2 :
关于格式的样子以及格式的问题,存在一些问题。为了清除这些,我在数组中包含了一个演示该问题的对象。请记住,在我的脚本中发生的是有一个import-csv正确格式化的CSV(有多行等,并完美呈现),删除不必要的对象(使用$ array.Remove),然后转储到文件( Out-File或Export-Csv)。如此简单,却如此破碎......
示例数组对象(Out-File):
@ {插件ID = #####; CVE = CVE - #### - ####; CVSS = ##。风险=中;主机= ### ### ### ###。。。;协议= XXX;端口= ##; Name = Microsoft ASP.NET xxx;概要=远程Web服务器使用的框架
漏洞;说明=在远程主机上运行的Web服务器似乎正在使用Microsoft
ASP.NET,可能受漏洞影响。
此外,有人猜测可能会导致此漏洞 如果攻击者具有物理访问机器,则在独角兽和彩虹中 插上电源。解决方案=使用魔术过滤器阻止对顽皮网站的请求。插件输出= Nessus通过请求发送了一个顽皮的页面或相关的错误消息 以下网址:
hxxp://###.###.###.###/xxx/xxxxxxxxx
}
示例数组对象(Export-Csv):
#TYPE System.String
“长度”
“616”
答案 0 :(得分:2)
问题似乎在于你如何操纵数组。看看这个:
Test.csv
"Age";"Name"
12;"Test name"
13;"My Other
test"
脚本
$Array = Import-Csv .\test.csv -Delimiter ";"
#$Array.Remove() is NOT a valid method. An array is of fixed size, and you will get an exception
#Instead, create a new array of items that are filtered through your rules.
#My test rule is only kids who are not 12 years old
$Newarray = $Array | Where-Object { $_.Age -ne "12" }
$Newarray | Export-Csv .\out.csv -Delimiter ";" -NoTypeInformation
Out.csv
"Age";"Name"
"13";"My Other
test"
一切都应该如此。
请勿在对象上使用-replace
。它会将对象转换为字符串,您将获得update2中提供的输出。例如:
$Array = Import-Csv .\test.csv -Delimiter ";"
$Array -replace "`r`n" | Export-Csv .\out2.csv -Delimiter ";"
$Array -replace "`r`n" | Out-File out2.txt
Out2.csv
#TYPE System.String
"Length"
"25"
"28"
“TYPE”部分只是因为您没有使用-NoTypeInformation
指定Export-CSV
Out2.txt
@{Age=12; Name=Test name}
@{Age=13; Name=My Othertest}
顺便说一句,Out-File
不是导出对象的方法,但是,在-replace
对象数组成为字符串数组之后,就像Out2.txt中的输出
编辑 $OutterArrayScanMe = @($arrayHeader) + @($InnerArrayScanMe)
这是您的问题。您将两个数组合并在一起。新数组中的第一个对象是一个字符串对象。 Export-CSV
使用第一个对象的属性作为每个对象的标题。由于第一个对象是一个字符串(只有Length属性),因此所有对象都将仅以Length
属性导出。
如上所述,Export-CSV
使用对象属性作为标题(除非您指定另一个标头定义,如| Select Age, Name | Export-Csv
)。因此,如果$InnerArrayScanMe
是具有相同属性的对象数组,只需使用:
$InnerArrayScanMe | Export-Csv "$dirResults\$FileScanMe-$startTime.csv" -Delimiter ";" -NoTypeInformation
和Export-CSV
将自己找出标题。简介:请勿将您的标题字符串添加到数组中。如果您需要特定订单或者需要排除某些属性,您可以使用传递字符串数组来select-object
定义标题,如下所示:
$arrayHeader = @("Plugin ID","CVE","CVSS","Risk","Host","Protocol","Port","Name","Synopsis","Description","Solution","Plugin Output")
$arrlist | Select-Object -Property $arrayHeader |
Export-Csv "$dirResults\$FileScanMe-$startTime.csv" -Delimiter ";" -NoTypeInformation
答案 1 :(得分:1)
不确定您的问题,您可以执行以下操作:
Import-Csv C:\temp\nessus.csv | where {$_.risk -eq "high"}
Import-Csv C:\temp\nessus.csv | where {$_.risk -eq "high"} | select host -Unique
您可以将其导出为可使用Excel编辑的CSV
Import-Csv C:\temp\nessus.csv | where {"high","medium","low" -contains $_.risk} | select "Plugin ID", CVE, CVSS, Risk, Host, Protocol, Port, Name | Export-Csv 'c:\temp\nessusExcel.csv' -Delimiter ';'
您可以在gridview中显示:
Import-Csv C:\temp\nessus.csv | where {"high","medium","low" -contains $_.risk} | select "Plugin ID", CVE, CVSS, Risk, Host, Protocol, Port, Name | Out-GridView
导出到HTM文件:
Import-Csv C:\temp\nessus.csv | where {"high","medium","low" -contains $_.risk} | select "Plugin ID", CVE, CVSS, Risk, Host, Protocol, Port, Name | ConvertTo-Html -As List > report.html
答案 2 :(得分:0)
问题在于脚本,在此步骤:
$InnerArrayScanMe = New-Object System.Collections.ArrayList
# This method keeps the arrays separate types
FOREACH ( $Object in $OutterArrayScanMe )
{ $InnerArrayScanMe.Add("$Object") | Out-Null }
$ InnerArrayScanMe成功地添加了普通数组$ OutterArrayScanMe中的对象,而没有更改数组类型,但是因为它被放入.NET数组中,所以数据的格式不正确。
最初的方法是这样我可以使用.NET数组的.Add和.Remove方法。解决方法使我们不需要引用要通过索引删除的对象,如下所示:
FOREACH ( $Exception in $ArrayException )
{
$ArrayScanMe = $ArrayScanMe | Where-Object {"$_" -ne "$Exception"};
}
然后我们可以做一个基本的Export-Csv
$ArrayScanMe | Export-Csv "$dirResults\$FileScanMe-$startTime.csv" -Delimiter "," -NoTypeInformation