PowerShell:从数组创建PSCustomObject

i34xakig  于 2023-03-30  发布在  Shell
关注(0)|答案(4)|浏览(106)

我有一个PowerShell-Object $foo,它有两个属性:ColumnRow。每个属性都包含一个项目数组:

$foo.Column
{Cost, UsageDate, Currency}

$foo.Row
{120, 20230301, USD, 150, 20230302, USD, 200, 20230303, USD ... }

我如何从它得到一个PS-CustomObject $bar,看起来像这样

$bar | Format-Table

Cost     UsageDate     Currency
----     ---------     --------
120      20230301      USD
150      20230302      USD
200      20230302      USD
i2loujxw

i2loujxw1#

如果这就是$foo对象的样子,可以像下面这样做

$foo = [PsCustomobject]@{
    Column = 'Cost', 'UsageDate', 'Currency'
    Row    = '120', '20230301', 'USD', '150', '20230302', 'USD', '200', '20230303', 'USD'  # etcetera
}

然后将数据创建为PsCustomObject:

$bar = for ($r = 0; $r -lt ($foo.Row.Count - 2); $r += 3) {
    $temp = [ordered]@{}
    for($i = 0; $i -lt $foo.Column.Count; $i++) {
        $temp[$foo.Column[$i]] = $foo.Row[$i + $r]
    }
    [PsCustomobject]$temp
}
# output on screen

$bar

甚至

$header = ($foo.Column | ForEach-Object { '"{0}"' -f $_ }) -join ','
$data = for ($r = 0; $r -lt ($foo.Row.Count - 2); $r += 3) {
    ($r..($r + 2) | ForEach-Object { '"{0}"' -f $foo.Row[$_] }) -join ','
}

$bar = $header, $data | ConvertFrom-Csv
# output on screen
$bar

输出:

Cost UsageDate Currency
---- --------- --------
120  20230301  USD     
150  20230302  USD     
200  20230303  USD
aamkag61

aamkag612#

你可以使用for循环在Rows和Columns以及一个有序字典之间顺序迭代来创建一个新对象。例如:

$foo = [pscustomobject]@{
    Column = 'Cost', 'UsageDate', 'Currency'
    Row    = '120', '20230301', 'USD'
}

$result = [ordered]@{}
for($i = 0; $i -lt $foo.Column.Length; $i++) {
    $result[$foo.Column[$i]] = $foo.Row[$i]
}
[pscustomobject] $result

如果对象有多行,则需要更改逻辑:

$foo = [pscustomobject]@{
    Column = 'Cost', 'UsageDate', 'Currency'
    Row    = '120', '20230301', 'USD', '120', '20230301', 'USD'
}

$result = [ordered]@{}; $i = 0
foreach($row in $foo.Row) {
    $result[$foo.Column[$i++]] = $row
    if($i -eq $foo.Column.Length) {
        $i = 0
        [pscustomobject] $result
        $result.Clear()
    }
}
bvk5enib

bvk5enib3#

一个避免递增索引的一行程序如何?
创建一个.csv的多行字符串,并将其通过管道传输到ConvertFrom-Csv

$bar = ($foo.Column -join ','), ( ($foo.Row -join ',') -replace '(?=\,\d+\,\d{8}\,[A-Z]{3})\,',"`n" ) -join "`n" | ConvertFrom-Csv

实际应用:

PS > $foo = [PsCustomobject]@{
>>     Column = 'Cost', 'UsageDate', 'Currency'
>>     Row    = '120', '20230301', 'USD', '150', '20230302', 'USD', '200', '20230303', 'USD'
>> }
PS >
PS > $bar = ($foo.Column -join ','), ( ($foo.Row -join ',') -replace '(?=\,\d+\,\d{8}\,[A-Z]{3})\,',"`n" ) -join "`n" | ConvertFrom-Csv
PS >                                                                                    PS > $bar

Cost UsageDate Currency
---- --------- --------
120  20230301  USD
150  20230302  USD
200  20230303  USD

-replace运算符的match表达式使用正向前查找,只匹配后面跟有以下字符的逗号:

  • <digits>,<8 digits>,<3 letters>

并将其替换为换行符,创建.csv的行。
因此,唯一真实的的脑力工作是创建将匹配整行数据的正则表达式。

zzlelutf

zzlelutf4#

谢谢你们!我是这样解决的:
首先创建一个空对象:

$temp = @()

将标题添加到对象

$temp = @()
$temp += $foo.columns.name -join ";"

将行添加到对象:

$temp += $foo.rows -replace(" ",";")

并将其转换为:

$bar = $temp | ConvertFrom-Csv -Delimiter ";"

相关问题