我有一个Powershell脚本,我用它来解析文件中的每一行,重新格式化它,并将新字符串写入输出文件。它与几百行的输入文件一起工作正常。但是,我需要最终针对一个有几百万行的文件来运行它,我已经等了好几个小时但它还没有完成。在this post之后,我想我需要将写输出放在循环之外,但到目前为止我还没有成功。
这是我目前的代码:
Foreach ($line in Get-Content $logFile) {
$arr = $line.Split()
$port1 = $arr[9].Split(":")
$port2 = $arr[11].Split(":")
$connstring = '|' + $port1[0] + "|" + $port1[1] + "|" + $port2[0] + "|" + $port2[1] + "|" + $arr[4] + "|"
Write-Output $connstring | Out-File "C:\logging\output\logout.txt" -Append
}
输入字符串的示例是:
06/14-04:40:11.371923 [**] [1:4:0] other [**] [Priority: 0] {TCP} 67.202.196.92:80 -> 192.168.1.105:55043
我需要将其重新格式化为:
|67.202.196.92|80|192.168.1.105|55043|other|
非常感谢任何帮助!
答案 0 :(得分:3)
如果在-ReadCount
上使用Get-Content
,它将一次一行地传输文件,而不必将整个文件读入内存。我怀疑在循环之外移动写操作可能会更快。循环中较少的变量和步骤也可能有所帮助。
假设分割后的第四个元素不包含冒号(你没有提供和你的文件的例子)那么这样的东西应该可以做到这一点:
Get-Content $logFile -ReadCount 1 | % {
'|' + (($_.Split()[9, 11, 4] -replace ':', '|') -join '|') + '|'
} | Out-File "C:\logging\output\logout.txt"
答案 1 :(得分:1)
可能有助于删除字符串构造中的添加
$connstring = "|$($port1[0])|$($port1[1])|$($port2[0])|$($port2[1])|$($arr[4])|"
尝试使用Measure-Command
测试样本数据集。
答案 2 :(得分:1)
尝试这样的事情:
$test="06/14-04:40:11.371923 [**] [1:4:0] other [**] [Priority: 0] {TCP} 67.202.196.92:80 -> 192.168.1.105:55043"
$template=@"
{Row:06/14-04:40:11.371923 [**] [1:4:0] {Text:other} [**] [Priority: 0] \{TCP\} {IPIN:67.202.196.92}:{PORTIN:80} -> {IPOUT:192.168.1.105}:{PORTOUT:55043}}
"@
$test| ConvertFrom-String -TemplateContent $template |%{"|{0}|{1}|{2}|{3}|{4}|" -f $_.Row.IPIN, $_.Row.PORTIN, $_.Row.IPOUT , $_.Row.PORTOUT , $_.Row.Text }
但您可以像这样直接导出到csv:
$template=@"
{Row:06/14-04:40:11.371923 [**] [1:4:0] {Text:other} [**] [Priority: 0] \{TCP\} {IPIN:67.202.196.92}:{PORTIN:80} -> {IPOUT:192.168.1.105}:{PORTOUT:55043}}
"@
Get-Content $logFile | ConvertFrom-String -TemplateContent $template | % {
[pscustomobject]@{
IPIN=$_.Row.IPIN
PORTIN=$_.Row.PORTIN
IPOUT=$_.Row.IPOUT
PORTOUT=$_.Row.PORTOUT
Text=$_.Row.Text
}
} | export-csv "C:\logging\output\logout.csv" -Append -NoType