Powershell ForEach-Object 列变量

问题描述

有点奇怪的问题。我有一个需要处理的大型 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"}
]

最终结果应该是我有 5 个文件

  • 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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...