问题描述
有点奇怪的问题。我有一个需要处理的大型 JSON 文件。基于另一个问题,我需要流式传输文件,否则它会因为内存而给我带来问题:JSON Powershell memory issue
我拥有的是这个:
get-content -Path largefile.json | ForEach-Object {
$row = $_ = $_.Trimstart('[').TrimEnd(']')
if ($_) { $_ | Out-String | ConvertFrom-Json }
New-Item -Path $($Row.Id).txt
Set-Content -Path $($Row.Id).txt -Value ($row.Body)
}
我可以轻松地执行 $row 以在 Largefile.json 中发布最后处理的行。我想在当前处理的行中创建一个具有 Id 名称的文件,并将 body 列添加到文件中。但是当我想使用 $row.Id 显示特定列时,不幸的是这显示为空。
Largefile.json 的结构如下:
[{"Id":"1","ParentId":"parent","Name":"filename","OwnerId":"owner","CreatedDate":"date","Body":"data1"}
{"Id":"2","Body":"data2"}
{"Id":"3","Body":"data3"}
{"Id":"4","Body":"data4"}
{"Id":"5","Body":"data5"}
]
-
1.txt - 文件内的值应该是:data1
-
2.txt - 文件内的值应该是:data2
-
3.txt - 文件内的值应该是:data3
-
4.txt - 文件内的值应该是:data4
-
5.txt - 文件内的值应该是:data5
我使用 Powershell 7.1.3
有什么方法可以像普通 ForEach 那样使用 $row.Id 和 $row.ParentId 吗?
感谢您的帮助。
解决方法
我仍然不确定您期望的结果。
但我认为你想这样做:
@'
[{"Id":"1","ParentId":"parent1","Name":"1.txt","OwnerId":"owner","CreatedDate":"date","Body":"Data1"}
{"Id":"2","ParentId":"parent2","Name":"2.txt","Body":"Data2"}
{"Id":"3","ParentId":"parent3","Name":"3.txt","Body":"Data3"}
{"Id":"4","ParentId":"parent4","Name":"4.txt","Body":"Data4"}
{"Id":"5","ParentId":"parent5","Name":"5.txt","Body":"Data5"}
]
'@ | Set-Content .\largefile.json
Get-Content .\largefile.json | ForEach-Object {
$_ = $_.TrimStart('[').TrimEnd(']')
If ($_) {
$Row = ConvertFrom-Json $_
Set-Content -Path ".\$($Row.Name)" -Value $Row.Body
}
}
,
在我看来,这就是您要找的:
Get-Content largefile.json | ForEach-Object {
$row = $_.TrimStart('[').TrimEnd(']') | ConvertFrom-Json
if ($null -ne $row) {
Set-Content -Path ($row.Id) -Value ($row.Body)
}
}
,
这个问题有很多错误。假设 json 中缺少逗号,如果我理解这个问题,我会这样做。这应该适用于问题的新更新。我还有一个更不寻常的解决方案,涉及使用 jq 流式传输 json:Iterate though huge JSON in powershell 稍后可能会添加 Json 流支持:ConvertFrom-JSON high memory consumption #7698
[{"Id":"ID","ParentId":"parent","Name":"filename","Body":"*******"},{"Id":"ID","Body":"*******"}
]
get-content -Path largefile.json | ForEach-Object {
$_ = $_.TrimStart('[').TrimEnd(']').TrimEnd(',')
if ($_) {
$row = $_ | ConvertFrom-Json
Set-Content -Path ($Row.Id + '.txt') -Value $row.Body
}
}
get-content ID.txt
*******
,
正如其他人已经解释过的,您的 json 示例无效。
但是,由于这是一个要处理的巨大文件,因此您可以使用 switch
。
switch -Regex -File D:\Test\largefile.json {
'"Id":"(\d+)".*"Body":"(\w+)"' {
Set-Content -Path ('D:\Test\{0}.txt' -f $matches[1]) -Value $matches[2]
}
}
使用您的示例的结果将是 5 个名为 1.txt
.. 5.txt
的文件,每个文件都有一行 data1
.. data5