如何解决用于大分隔文件聚合操作的 Powershell 性能调整
我有一个包含 350 列的分隔文件。分隔符是 \034(Field separator)
。
我必须提取特定的列值并找出文件中该列的每个不同值的计数。如果不同值的计数大于或等于 2,我需要将其输出到文件。
源文件是 1GB。我写了以下命令。很慢。
Get-Content E:\Test\test.txt | Foreach {($_ -split '\034')[117]} | group-object -Property { $_ } | %{ if($_.Count -ge 2) { Select-Object -InputObject $_ -Property Name,Count} } | Export-csv -Path "E:\Test\test2.csv" -NoTypeinformation
请帮忙!
解决方法
我建议使用 switch
statement 来快速处理输入文件(根据 PowerShell 标准):
# Get an array of all the column values of interest.
$allColValues = switch -File E:\Test\test.txt {
default { # each input line
# For better performance with *literal* separators,# use the .Split() *method*.
# Generally,however,use of the *regex*-based -split *operator* is preferable.
$_.Split([char] 0x1c)[117] # hex 0x1c is octal 034
}
}
# Group the column values,and only output those that occur at least
# twice.
$allColValues | Group-Object -NoElement | Where-Object Count -ge 2 |
Select-Object Name,Count | Export-Csv E:\Test\test2.csv -NoTypeInformation
感谢 Mathias R. Jessen 建议使用 -NoElement
开关,它通过仅维护抽象组信息来简化 Group-Object
调用;也就是说,只有分组标准(反映在 .Name
中,而不是组成组的单个对象(通常反映在 .Group
中)通过输出返回对象。
至于你尝试了什么:
-
Get-Content
在管道中逐行流式传输慢,通常(逐对象传递引入了开销) 并且,特别地,因为Get-Content
用 ETS(扩展类型系统)元数据装饰它输出的每一行。- GitHub issue #7537 建议添加一种选择退出这种装饰的方法。
- 以内存消耗和潜在的行拆分额外工作为代价,
-Raw
开关将整个文件作为单行多行字符串读取,这要快得多。
-
不需要将
-Property { $_ }
传递给Group-Object
- 只需省略它。如果没有-Property
参数,输入对象将作为一个整体分组。 -
链接
Where-Object
和Select-Object
- 而不是通过ForEach-Object
调用中的if
语句与 multiple {{ 1}} 调用 - 不仅在概念上更清晰,而且性能更好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。