powershell - 在PowerShell中解析数​​千个小文件的最快方法

标签 powershell

我在网络共享上有16000多个 list 日志文件,大小从3-5 KB不等。
示例文件如下所示:

## System Info
SystemManufacturer:=:Dell Inc.                
SystemModel:=:OptiPlex GX620               
SystemType:=:X86-based PC
ChassisType:=:6 (Mini Tower)

## System Type
isLaptop=No

我需要将它们放入数据库中,因此我开始对其进行解析,并为每个对象创建一个自定义对象,以便以后用于检查重复项,规范化等。

如下所示,使用代码片段进行的初始解析大约需要7.5分钟。
Foreach ($invlog in $invlogs) {
    $content = gc $invlog.FullName -ReadCount 0
    foreach ($line in $content) {
        if ($line -match '^#|^\s*$') { continue }
        $invitem,$value=$line -split ':=:'
        [PSCustomObject]@{Name=$invitem;Value=$value}
    }
}

我开始对其进行优化,经过几次尝试和错误后,结果耗时2分钟4秒钟:
 Foreach ($invlog in $invlogs) {
        foreach ($line in ([System.IO.File]::ReadLines("$($invlog.FullName)") -match '^\w')  ) {
           $invitem,$value=$line -split ':=:'
           [PSCustomObject]@{name=$invitem;Value=$value}  #2.04mins
        }
    }

我也尝试使用哈希代替PSCustomObject,但是令我惊讶的是,它花了更长的时间(5分26秒)
       Foreach ($invlog in $invlogs) {                        
        $hash=@{}        
        foreach ($line in ([System.IO.File]::ReadLines("$($invlog.FullName)") -match $propertyline)  ) {

           $invitem,$value=$line -split ':=:'
           $hash[$invitem]=$value #5.26mins
        }
    }

在这里使用最快的方法是什么?

最佳答案

看看这是否更快:

Foreach ($invlog in $invlogs) {
@(gc $invlog.FullName -ReadCount 0) -notmatch '^#|^\s*$' |
 foreach {
          $invitem,$value=$line -split ':=:'
          [PSCustomObject]@{Name=$invitem;Value=$value}
         }
}

将-match和-notmatch运算符应用于数组时,它会返回满足匹配条件的所有元素,因此您可以不必为排除的行而测试每一行。

您是真的要为每一行创建一个PS对象,还是为每个文件创建一个PS对象?

如果您希望每个文件一个对象,请看这样是否更快:
多行正则表达式消除了行数组,并且使用过滤器代替foreach来创建哈希条目。
 $regex = [regex]'(?ms)^(\w+):=:([^\r]+)'
 filter make-hash { @{$_.groups[1].value = $_.groups[2].value} }

Foreach ($invlog in $invlogs) {
$regex.matches([io.file]::ReadAllText($invlog.fullname)) | make-hash
 }

切换到使用多行正则表达式和[io.file]::ReadAllText]的目的是简化Powershell在内部使用文件输入进行的操作。 [io.file]::ReadAllText()的结果将是一个字符串对象,这是一种比[io.file]::ReadAllLines()产生的字符串数组简单得多的对象类型,并且所需的开销更少在内部进行组织。过滤器本质上只是一个函数的Process块-它会针对管道中的每个对象运行一次,因此它模仿了foreach-object的操作,但实际上运行速度略快(我不知道内部原理足以告诉您确切的原因)。这两个更改都需要更多的编码,并且只会导致性能的少量提高。在我的测试中,切换到多行文件每个文件大约获得0.1毫秒,然后从foreach-object更改为过滤器再增加0.1毫秒。与所需的其他编码工作相比,您可能看不到这些技术的使用率很高,因为它们的返回率很低,但是当您开始将这些毫秒的分数乘以160K迭代时,它就变得很重要。

关于powershell - 在PowerShell中解析数​​千个小文件的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20082369/

相关文章:

powershell - Azure使用powershell如何获取实例计数

powershell - 从Powershell(Get-ADuser)的写主机输出中删除某些字符

PowerShell FileInfo在子目录中输出文件

c# - .NET https身份验证(Pingdom API)

powershell - 使用 PowerShell 命令 Start-Process 安装 msi 时,出现退出代码 1603 错误

powershell - PowerShell 中是否有一种方法可以在不缩短单词的情况下截断字符串

powershell - 什么是文件系统提供程序过滤器语法?

powershell - 为 Windows 10 安装 Active Directory 模块 powershell

Powershell Get-ChildItem -Filter 与具有相同值的 Where 子句的操作不同

powershell - 如何在 PowerShell 提示符下(不在脚本中)初始化多行数组?