Export-CSV cmdlet在FOREACH语句的每次迭代期间重写整个CSV



我正在使用一些代码,这些代码将获取一系列性能计数器,然后将计数器放入.csv文件中,每次达到1MB时都会滚动。

$Folder="C:PerflogsBBCRMLogs" # Change the bit in the quotation marks to whatever directory you want the log file stored in
$Computer = $env:COMPUTERNAME
$1GBInBytes = 1GB
$p = LOTS OF COUNTERS;
# If you want to change the performance counters, change the above list. However, these are the recommended counters for a client machine. 
$num  = 0
$file = "$FolderSQL_log_${num}.csv"
if( !(test-path $folder)) {New-Item $Folder -type directory}
Get-Counter -counter $p -SampleInterval 2 -Continuous | Foreach {
    if ((Get-Item $file -ErrorAction SilentlyContinue ).Length -gt 1mb) 
    {
        $num +=1
        $file = "$FolderSQL_log_${num}.csv"
    }
    $_
} | Foreach-Object { $_ | Export-Csv $file -Force -Append}

现在,它工作得很好。迭代工作得很好,并且每次.csv达到1MB时都会创建一个新文件。但是,第一个. csv文件之后的每个. csv文件都是在2分钟后以1MB的大小创建的,这将导致创建一个新文件。我不太确定为什么会发生这种情况,尽管我相信这是因为Powershell每次创建csv时都会重写整个。csv。

[我把这个作为一个新的答案而不是编辑原来的答案,因为它是完全不同的。替换或追加原答案会使随后的讨论变得混乱。[/em>

您需要做的是使用正则表达式从Get-Counter输出的读数属性中提取值,并从时间戳和这些值手动构造CSV输出。将最后一行更改为(根据您喜欢的样式格式):

| %{'"' + (Get-Date $_.Timestamp -f 's') + '","' + (([regex]::matches($_.Readings, '(?<=\\.+?:n)(.+?)(?=n)') | select -ExpandProperty Value) -join '","') + '"'} | Out-File $file -Append -Encoding ASCII

分解:

  • (Get-Date $_.Timestamp -f 's')这部分不是严格必要的,尽管我认为它会使您的结果更容易遵循。's'格式将日期置于ISO 8601可排序模式中。您可以将'u'替换为另一种可排序的格式,或者使用您喜欢的自定义格式字符串。或者将其替换为$_。时间戳保留原始格式
  • [regex]::matches($_.Readings, '(?<=\\.+?:n)(.+?)(?=n)') regex匹配任何以\开头并以:结束的行(您想要摆脱的那些讨厌的计数器名称)的内容。请注意,我使用的是[regex]::matches,它执行全局匹配,而不是[regex]::match-match,它只会给您每个字符串的第一个匹配(读数属性是单个字符串,因此只会返回第一个计数器读数)。
  • | select -ExpandProperty Value生成所有匹配项的数组,然后您可以将其与","连接,并将"环绕以生成CSV输出。

由于没有使用转换函数,因此还需要构造标题行。在管道的正上方添加这一行:

`'"Timestamp","' + ($p -join '","') + '"' | Out-File $file -Append -Encoding ASCII`

假设$p是一个数组(它应该是)。如果它是一个字符串,那么根据格式的不同,您可以直接使用它,也可以将拆分为并以CSV格式重新连接。

将最后一行更改为这样,将每行转换为CSV格式,然后将其附加到输出文件:

} | Foreach-Object {($_ | ConvertTo-Csv -NoTypeInformation)[1] | Out-File $file -Append -Encoding ASCII}.

注意事项:

  • -Encoding ASCII不是严格必要的,但你可能有问题与Unicode CSV文件在一些应用程序(Excel,例如,默认情况下不会打开它作为CSV文件,一切都将在列a)
  • ($_ | ConvertTo-Csv -NoTypeInformation)[1]中索引的原因是ConvertTo-Csv -NoTypeInformation每次仍然输出标题行,所以您想要获取两行输出的第二行(($_ | ConvertTo-Csv -NoTypeInformation)[0]是标题行)
  • 由于您没有输出标题行,因此需要在循环
  • 之前向$file输出一行。

最新更新