【问题标题】:powershell script consuming all memorypowershell脚本消耗所有内存
【发布时间】:2015-03-03 20:45:47
【问题描述】:

我正在运行以下脚本来检查一组文件的卡号。当我对一组总共 600mb 的 38 个文件运行它时,它会消耗最大 cpu(50% 受限)和最大内存(3.3GB 的 4.0GB 物理)。

寻找关于为什么会这样以及如何优化的想法。

谢谢!

Get-ChildItem "c:\REGEX\ScanMeFiles\" -Recurse |`
Foreach-Object{
    $content = Get-Content $_.FullName
    $outfile = 'c:\regex\results\'+$_.BaseName+'_results.log'
 $content | Where-Object {$_ -match '\b(?:3[47]\d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b'}  | Set-Content $outfile
}

【问题讨论】:

  • 你在反向引用中有反向引用。也许这是灾难性的回溯?尝试一个更简单的正则表达式,它使用更少的环顾四周。
  • 所以您正在寻找 Visa、MasterCard、AMEX 和 Discover 是吗?看起来您不关心连字符或空格的存在。那是对的吗?如果是这样,我们可以删除?:'s。您也可以考虑制作多个后台作业并限制一次运行的作业数量,例如answer(还有其他。)。 Select-String 也可以处理模式文件。不确定它是否比您现有的更有效。
  • 您好 jpmc26,谢谢,但我不确定是正则表达式的问题。首先,我应该说该代码中的所有内容都是从 Internet 的 4 个角落复制的(正则表达式和 powershell 脚本对我来说是外语)。如果我针对单个 3GB 文件运行该正则表达式,它运行得非常快(大约 10 分钟),同时按照我描述的针对总计 600mb 的多个文件运行它,我不得不在 50 分钟后终止该进程。所以我认为这是代码部分的内容。谢谢。
  • 嗨,马特,你是对的。我不认为我想要并行处理,因为它已经消耗了最大 cpu 和内存。不确定我拥有的代码是如何运行的,因为我只是从各种来源将这些代码混合在一起。我认为您可能对 Select-String 是正确的。我会试试看。谢谢!
  • 马特,选择字符串就是答案!这是我的结论(不知道如何格式化以使其易于理解......): Get-ChildItem "c:\REGEX\ScanMeFiles\" | Foreach-Object{ $content = $_.FullName $outfile = 'c:\regex\results\'+$_.BaseName+'results.log' $regex = '\b(?:3[47]\ d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b' 选择字符串 -Path $content -Pattern $regex -AllMatches | % { $.Matches } | % { $_.Value } | Set-Content $outfile 感谢您的帮助!!!

标签: regex powershell


【解决方案1】:

我会让它更包容一点。用更少的变量做这样的事情:

$children = (Get-ChildItem).FullName
foreach($child in $children){
    Get-Content $child | ?{$_ -match '\b(?:3[47]\d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b'} | Set-Content ('c:\regex\results\'+$_.BaseName+'_results.log')
}

【讨论】:

  • 虽然这使代码更简洁,但我认为它对内存消耗没有任何实际影响。 OP 可能需要考虑文件流
  • 这有很大的不同。我在对数以万计的邮箱和 MSOL 对象进行自动化处理时了解到这一点。他的方法获取所有对象并将它们存储在 RAM 中并一个一个地处理整个对象,这将比仅获取全名作为字符串而不是整个对象并使用所需的信息量最少。
【解决方案2】:

在马特的帮助下,这就是我想出的。针对我的测试数据在

Get-ChildItem "c:\REGEX\ScanMeFiles\" |
Foreach-Object{
    $content = $_.FullName
    $outfile = 'c:\regex\results\'+$_.BaseName+'_results.log'
    $regex = '\b(?:3[47]\d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b'
select-string -Path $content -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value } | Set-Content $outfile

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 2018-03-21
    • 2020-09-04
    相关资源
    最近更新 更多