基于计算每行的分隔符的出现次数,将多行合并为一行

时间:2017-04-06 22:40:40

标签: windows powershell batch-file

我有这样的数据:

RE_1|Emp_1|cty_1|analyst_1|end
RE_2|EMP_2|cty_2|analyst_2|end
RE_3|EMP_3|cty
_3|analyst_3|end
RE_4|EMP_4|cty_4|analyst_4|end

第三行分为两行。我需要将这些分割线合并为一个。每行应该有4个管道分隔符。所以我需要计算每一行|的数量。如果是4打印线。如果不是4,则将下一行合并,然后检查计数。如果它仍然不是4,也合并下一行。重复直到该行包含4个|分隔符。

原始文件包含数百万行,其中10000个像这样拆分。因此,我需要在PowerShell或Windows批处理中快速合并这些行的解决方案。

1 个答案:

答案 0 :(得分:2)

您可以使用这样的正则表达式:

... -replace '(?ms)^((?:[^\|\r\n]*\|){2}[^\|\r\n]*?)\r?\n((?:[^\|\r\n]*\|){2}end)', '$1$2'

但是,我不建议处理内存中有数百万条记录的文件。当你的计算机由于内存耗尽而开始交换后停止工作时,这并不是很有趣。在管道中处理文件可以避免这种问题:

$merged = ''
Get-Content 'C:\path\to\input.txt' | ForEach-Object {
  if ($_ -notlike '*|*|*|*|*') {
    # if the line doesn't have 4 pipe characters in it: append it to the
    # merged line variable and move on to the next line
    $merged += $_
  } else {
    # if the line does have 4 pipe characters in it: output and clear the
    # merged line variable if it contains a value, then output the current
    # line
    if ($merged) {
      $merged
      $merged = ''
    }
    $_
  }
} | Set-Content 'C:\path\to\output.txt'

# if the input file didn't end with a non-wrapped line the trailing wrapped lines
# haven't been written to the output file yet
if ($merged) {
  $merged | Add-Content 'C:\path\to\output.txt'
}