gpt4 book ai didi

json - 从 Powershell 中的超大文件中提取多行正则表达式

转载 作者:行者123 更新时间:2023-12-02 18:33:49 25 4
gpt4 key购买 nike

我有 CSV 格式的超大日志文件,其中包含 JSON 格式的数据。我想做的是从数据中提取 JSON 部分并将其存储在单独的文件中。

真正的问题是文件大小几乎为 70Gb,这会导致一些有趣的问题需要解决。文件大小使得无法以一大块读取整个文件。通过 Powershell 的 Get-Content 与 -ReadCount 和 Foreach-Object 相结合,我可以获取较小的 block 并在它们上逐 block 运行正则表达式模式。

$Path = <pathToFile>
$outPath = <pathToOutput>
Out-File -Encoding utf8 -FilePath $outPath
$JsonRegex = "(?smi)\{.*?\}"
Get-Content -Path $Path -ReadCount 100000 | Foreach-Object {
( "$_" | Select-String -Pattern $JsonRegex -AllMatches | Foreach-Object { $_.Matches } | Foreach-Object { $_.Value } ) | Add-Content $outPath
}

但这里发生的情况是,每 100k 行 ReadCount 就位于 JSON 对象的中间,因此会跳过该对象并从下一个对象继续。

以下是此日志数据的示例。它在第一行包含一些列,然后是 JSON 格式的数据,这些数据不一致,因此我无法使用任何固定的 ReadCount 值来避免位于 JSON 对象的中间。

"5","5","9/10/2019 12:00:46 AM","2","some","data","removed","comment","{
"message": "comment",
"level": "Information",
"logType": "User",
"timeStamp": "2019-09-10T03:00:46.5573047+03:00",
"fingerprint": "some",
}","11"
"5","5","9/10/2019 12:00:46 AM","2","some","data","removed","comment","{
"message": "comment",
"level": "Information",
"logType": "User",
"timeStamp": "2019-09-10T03:00:46.5672713+03:00",
"fingerprint": "some",
"windowsIdentity": "LOCAL\\WinID",
"machineName": "TK-141",
"processVersion": "1.0.71",
"jobId": "24a8",
"machineId": 11
}","11"

有什么方法可以完成此任务,而不会丢失巨大日志文件中的任何数据行?

最佳答案

使用 switch带有 -Regex-File 参数的语句可以高效(按照 PowerShell 标准)逐行读取文件并保持多行状态。

为了高效写入文件,请使用 .NET API,即 System.IO.StreamWriter实例。

以下代码假设:

  • 每个 JSON 字符串跨越多行并且是非嵌套的。
  • 在给定行上,开始 {/结束 } 明确标记(多行)JSON 字符串的开始/结束。
# Input file path 
$path = '...'

# Output file path
# Important: specify a *full* path
$outFileStream = [System.IO.StreamWriter] "$PWD/out.txt"

$json = ''
switch -Regex -File $path {
'\{.*' { $json = $Matches[0]; continue }
'.*\}' {
$json += "`n" + $Matches[0]
$outFileStream.WriteLine($json)
$json = ''
continue
}
default { if ($json) { $json += "`n" + $_ } }
}
$outFileStream.Close()

如果您可以进一步假设 JSON 字符串中没有任何部分位于同一行的开头 {/结尾 } 之前,如示例数据所示,那么您可以简化(并加速)switch 语句:

$json = ''
switch -Regex -File $path {
'\{$' { $json ='{'; continue }
'^\}' { $outFileStream.WriteLine(($json + "`n}")); $json = ''; continue }
default { if ($json) { $json += "`n" + $_ } }
}
$outFileStream.Close()

Doug Maurer尝试过涉及 System.Text.StringBuilder 的解决方案实例,以优化组成每个 JSON 字符串的部分的迭代串联:

  • 但是,至少对于通过多次重复样本数据制作的输入文件,我在非正式测试中只看到了很小的性能提升。

  • 为了完整起见,这里是 System.Text.StringBuilder 解决方案:

$json = [System.Text.StringBuilder]::new(512) # tweak the buffer size as needed
switch -Regex -File $path {
'\{$' { $null = $json.Append('{'); continue }
'^\}' { $outFileStream.WriteLine($json.Append("`n}").ToString()); $null = $json.Clear(); continue }
default { if ($json.Length) { $null = $json.Append("`n").Append($_) } }
}
$outFileStream.Close()

关于json - 从 Powershell 中的超大文件中提取多行正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69077306/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com