我创建了一些Powershell脚本,它们专注于数据收集。我编写了一些函数,这些函数大部分都这样工作:
现在,export-csv直接在函数中使用。因此,本身没有返回值。
由于我仍在学习Powershell,因此我偶然发现了散列表,并想知道是否值得更改我的函数以将数据收集到散列表中,而不是直接导出所有填充有数据的变量。
我不知道什么是最佳实践。性能不是问题,但是我认为遍历数百台计算机,打开一个csv,对其进行写入,然后将其关闭可能并不是I / O的最佳选择。
或者,我可以想象在将所有收集到的数据输出之前将它们存储到一个哈希表(或多个哈希表)中可能会很困难。
你能帮我吗?最好的方法是什么?
最佳答案
对于这种情况,有两种常见的方法:
foreach
循环并将数据收集在变量中,然后将该变量导出到CSV。$data = foreach ($server in (Get-Content 'input.txt')) {
# do stuff here, then build a custom object from the results
New-Object -Type PSObject -Property @{
'ComputerName' = $server
...
}
}
$data | Export-Csv 'output.csv' -NoType
ForEach-Object
循环,在该循环中,您从管道读取输入,并通过管道将输出传递给Export-Csv
。Get-Content 'input.txt' | ForEach-Object {
# do stuff here, then build a custom object from the results
New-Object -Type PSObject -Property @{
'ComputerName' = $_
...
}
} | Export-Csv 'output.csv' -NoType
前一种方法提供了更好的性能,但缺点是所有数据都被读入内存(
foreach
循环无法写入管道)。如果您有大量数据,可能会导致内存耗尽。后一种方法可以抵抗内存耗尽,因为管道通常一次只能处理一个对象。但是,整体处理比
foreach
循环慢。在给定的情况下,这两种方法中哪种最好,取决于您正在处理的实际数据。
我不建议将
Export-Csv
放入您的处理函数中,至少在没有使其成为可选函数的情况下如此。一方面,从性能的 Angular 来看,这不是好习惯。在循环中调用函数时,必须重复打开文件。最好只打开一次,然后在写入所有数据后将其关闭。此外,您还可以通过将处理与输出分开来获得灵活性。让您的函数返回“原始”数据,您可以根据需要进行处理(写入CSV,显示给用户,传递给另一个应用程序,...)。让您的函数接受管道输入,例如像这样:
function Invoke-Foo {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
$InputObject,
...
)
Begin {
# initialize stuff here
}
Process {
$InputObject | ForEach-Object {
# do stuff here, then build a custom object from the results
New-Object -Type PSObject -Property @{
...
}
}
}
End {
# cleanup goes here
}
}
你可以在
foreach
循环中使用它$data = foreach ($server in (Get-Content 'input.txt')) {
Invoke-Foo $server
}
$data | Export-Csv 'output.csv' -NoType
以及管道:
Get-Content 'input.txt' | Invoke-Foo | Export-Csv 'output.csv' -NoType
如果由于某种原因您必须具有从函数内部将数据写入文件的能力,我可能会这样修改函数:
function Invoke-Foo {
[CmdletBinding()]
Param(
...
[Parameter(Mandatory=$false)]
[string]$Path,
[Parameter(Mandatory=$false)]
[switch]$Append,
...
)
...
Process {
$InputObject | ForEach-Object {
# do stuff here, then build a custom object from the results
$obj = New-Object -Type PSObject -Property @{
...
}
if ($PSBoundParameters.ContainsKey('Path')) {
$obj | Export-Csv $Path -NoType -Append:$Append.IsPresent
} else {
$obj
}
}
}
...
}
关于powershell - 将数据导出到CSV-每个返回值或首先将数据收集到哈希表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50815998/