我有大文件(每个至少20 MB)我需要查找字符串M(\d{10})
以下是我正在使用的脚本:
Get-Content -Path Test.log | %{ [Regex]::Matches($_, "M(\d{10})") } | %{ $_.Value } | select -Unique
这需要花费大量时间和更多CPU,请建议如何以更低的CPU使用率/更快的速度获得结果。
答案 0 :(得分:2)
简单地衡量一下自己(最小化缓存效果差异,首先重复):
Measure-Command {Get-Content -Path Test.log | %{ [Regex]::Matches($_, "M(\d{10})") } | %{ $_.Value } | select -Unique}
Measure-Command {Get-Content -Path Test.log | %{ [Regex]::Matches($_, "M(\d{10})") } | %{ $_.Value } | select -Unique}
Measure-Command {sls -Path Test.log "M(\d{10})" | %{ $_.Matches.Groups[1].Value } | select -Unique}
答案 1 :(得分:1)
(可能)使用管道是内存有效的,但是使用速度慢。
要加快处理速度,
避免管道,但这仅是您的数据可以整体装入内存的唯一选择-20 MB不会有问题文件。
分别直接使用.NET框架类型及其方法,通常比使用 cmdlet 更快。
将这些见解应用于您的情况(PSv3 +语法):
[regex]::Matches(
[IO.File]::ReadAllText($PWD.ProviderPath + '/Test.log'),
'M\d{10}'
).Value | Select-Object -Unique
请注意,为方便起见,Select-Object -Unique
仍使用流水线以获取唯一的出现次数,但是假设是处理的大部分(提取正则表达式匹配项)位于该声明。
答案 2 :(得分:0)
我不会多次使用Foreach-Object
,而是使用Select-String
:
(Get-Content -Path Test.log | Select-String "(?<=M)\d{10}").Matches.Value | select -Unique