将没有分隔符和100+列的4 GB固定列宽文本文件转换为修剪的制表符分隔文件

每月我收到几个非常大(〜4 GB)的固定列宽文本文件,需要将其导入MS SQL Server。要导入文件,必须将文件转换为带有制表符分隔的列值的文本文件,该列值的每个列值都修剪有空格(某些列没有空格)。我想使用PowerShell解决此问题,并且我希望代码非常快。

我尝试了许多代码迭代,但是到目前为止太慢或无法正常工作。我已经尝试过microsoft Text Parser(太慢了)。我试过正则表达式匹配。我正在安装Windows PowerShell的Windows 7计算机上工作。

Origin

感谢您能提供的任何帮助!

lucky123w 回答:将没有分隔符和100+列的4 GB固定列宽文本文件转换为修剪的制表符分隔文件

带有switch选项的-File语句是在PowerShell [1] 中处理大型文件的最快方法:

& { 
  switch -File $infile -Regex  {
    $match_regex {
       # Join the what all the capture groups matched,trimmed,with a tab char.
       $Matches[1..($Matches.Count-1)].Trim() -join "`t"
    }
  }
} | Out-File $outFile # or: Set-Content $outFile (beware encoding issues)

通过文本输出,Out-FileSet-Content可以互换使用,但是在 Windows PowerShell 中,它们默认情况下使用不同的字符编码(UTF-16LE与Ansi);根据需要使用-Encoding; PowerShell Core 始终使用无BOM的UTF-8。

注意:

  • 要跳过标头行或单独捕获它,请为其提供单独的正则表达式,或者,如果标头也与数据行正则表达式匹配,请在初始化行索引变量之前switch语句(例如$i = 0),然后在处理脚本块(例如if ($i++ -eq 0) { ... })中检查并递增该变量。

  • .Trim()返回的数组中的每个字符串上,
  • $Matches[1..($Matches.Count-1)]被隐式调用 ;此功能称为member enumeration

  • switch语句包含在script block调用的& { ... }call operator (&){ ... })中的原因是 compound 语句,例如switch / whileforeach (...),...作为管道输入-参见{{ 3}}。


关于您尝试过的事情

正如this GitHub issue所指出的那样,您不应使用$Input作为用户变量-它是由PowerShell管理的iRon,实际上,您分配给它的任何内容都是安静地丢弃

automatic variable指出:

  • $element = $_.trim()不起作用,因为您在foreach 循环内部,而不是在ForEach-Object 管道中cmdlet (即使后者也别名为foreach;只有使用ForEach-Object时,$_才会设置为当前输入对象。

  • 仅使用分隔符将数组的元素连接起来就不需要自定义函数。 -join运算符直接执行该操作,如上所示。

AdminOfThings展示了如何直接将-join$Matches数组一起使用,如上所述。

一些助手:

  

Join-Str($matches)

您应该改用Join-Str $matches

在PowerShell中,像外壳命令一样调用函数 -foo arg1 arg2-不像C#方法调用 -foo(arg1,arg2);参见Lee_Daily
如果使用,分隔参数,则将构造一个 array ,该函数会将其视为单个参数。
为防止意外使用方法语法,请使用Get-Help about_Parsing或更高版本,但请注意其其他效果。

  

| Out-Null

几乎总是更快的输出抑制方法是使用$null = ...


[1]与问题中的Get-Content + ForEach-Object方法相比,Mark(OP)报告了极大的提速(switch解决方案需要7.7分钟。 4GB的文件)。
尽管switch解决方案在大多数情况下可能足够快,但Set-StrictMode -Version 2显示的解决方案对于高迭代次数可能更快; this answerswitch解决方案进行了对比,并显示了具有不同迭代次数的基准。
除此之外,用C#编写的已编译解决方案是进一步提高性能的唯一方法。

,

这是我的工作代码的高层次。注意,使用System.IO.StreamReader对于使处理时间达到可接受的水平至关重要。感谢所有帮助我到达这里的帮助。

$posts
本文链接:https://www.f2er.com/3135215.html

大家都在问