合并两个CSV,然后在输出上重新排序列

ca1c2owp  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(117)

我有第一个CSV:

Server,Info  
server1,item1
server1,item1

第二个CSV:

Server,Info  
server2,item2
server2,item2

我试图得到这样的输出:

Server,Server,Info,Info
server1,server2,item1,item2
server1,server2,item1,item2

如您所见,问题在于两个CSV的头文件具有相同的名称,如果我将它们解析为对象并循环键,这将导致问题。
所以我尝试合并它们,然后将它们重新排序为字符串,但我的头脑无法想象如何在最后一个for循环中做到这一点:

$file1 = Get-Content ".\Powershell test\A.csv"
$file2 = Get-Content ".\Powershell test\B.csv"

$content = for ($i = 0; $i -lt $file1.Length; $i++) {
    '{0},{1}' -f $file1[$i].Trim(), $file2[$i].Trim()
}

$content | Out-File  ".\Powershell test\merged.csv"

$firstFileParsed = Import-Csv -Path ".\Powershell test\B.csv"
$secondFileParsed = Import-Csv -Path ".\Powershell test\B.csv"

$secondFilePath =  ".\Powershell test\B.csv"
$contentOf2ndFile = Get-Content $secondFilePath

$csvColumnNames = (Get-Content '.\Powershell test\B.csv' |
                  Select-Object -First 1).Split(",")

$newColumns = @()

foreach($header in $csvColumnNames) {
    $newColumns += $header
}

$newColumns = $newColumns -join ","
$contentOf2ndFile[0] = $newColumns
$contentOf2ndFile | Out-File ".\Powershell test\temp.csv"

$tempObject = Import-Csv -Path ".\Powershell test\temp.csv"
$tempFile = Get-Content ".\Powershell test\temp.csv"

$array = @()
$tempArr = @()

for ($i = 0; $i -lt $file1.Length; $i++) {
    $tempArr1 = $file1[$i] -split ","
    $tempArr2 = $tempFile[$i] -split ","

    for ($j = 0; $j -lt $tempArr1.Length; $j++) {
        $tempArr += $tempArr1[$j] +  "," + $tempArr2[$j]
        $tempArr
    }

    $array += $tempArr
}

$array | Out-File '.\Powershell test\merged.csv'
lawou6xi

lawou6xi1#

你建议的不是很有用,甚至不是有效的CSV。IMHO只有两个结果是有意义的:
这一点:

Server1,Info1,Server2,Info2
server1,item1,server2,item2
server1,item1,server2,item2

或者这个:

Server,Info
server1,item1
server1,item1
server2,item2
server2,item2

第一种方法:

$csv1 = Import-Csv ".\Powershell test\A.csv"
$csv2 = Import-Csv ".\Powershell test\B.csv"

$merged = for($i = 0; $i -lt $csv1.Count; $i++) {
    $new = new-object psobject
    $entry1 = $csv1[$i]
    $entry1 | Get-Member -Type NoteProperty | foreach {
        Add-Member -InputObject $new -MemberType NoteProperty -Name ($_.Name + "1") -Value $entry1.($_.Name)
    }
    $entry2 = $csv2[$i]
    $entry2 | Get-Member -Type NoteProperty | foreach {
        Add-Member -InputObject $new -MemberType NoteProperty -Name ($_.Name + "2") -Value $entry2.($_.Name)
    }
    $new
}

$merged | Export-Csv ".\Powershell test\merged.csv"

第二种方法:

$csv1 = Import-Csv ".\Powershell test\A.csv"
$csv2 = Import-Csv ".\Powershell test\B.csv"

$merged = $csv1 + $csv2

$merged | Export-Csv ".\Powershell test\merged.csv"

更新

如果你想要准确的输出(并且文件肯定有相同的标题和行数),你可以先使用唯一的标题,然后简单地重命名它们:

$csv1 = Import-Csv ".\Powershell test\A.csv"
$csv2 = Import-Csv ".\Powershell test\B.csv"
$merged = for($i = 0; $i -lt $csv1.Count; $i++) {
    $new = New-Object PSObject
    ("Server", "Info") | foreach {
        Add-Member -InputObject $new -MemberType NoteProperty -Name ($_ + "1") -Value $csv1[$i].$_
        Add-Member -InputObject $new -MemberType NoteProperty -Name ($_ + "2") -Value $csv2[$i].$_
    }
    $new
}
$header = $true
$merged | ConvertTo-Csv -NoTypeInformation | foreach {
    if ($header) {
        $header = $false
        # remove the numbers from the headers
        $_ -replace "\d", ""
    }
    else { $_ }
} | Out-File ".\Powershell test\merged.csv"
  • 说明:*

Count在Powershell中可用于所有集合,并且比Length更安全,后者仅是数组的属性。但在这种情况下,两者都应该起作用。
在循环中,创建一个新的空对象(使用New-Object),然后通过添加解析的CSV对象的成员(使用Add-Member)来填充。属性名称中添加了一个计数器,以使其唯一。
然后将这些对象的集合($merged)转换为CSV,删除标题行中的数字,并将所有内容保存到文件中。

uajslkp6

uajslkp62#

由于似乎有几个用例可以识别不相关的属性键,而不是将它们合并,因此我添加了一个新特性。Join-Objectcmdlet的-Unify(正式名称/别名为-Merge参数)现在接受一个或两个动态键来区分联接中不相关的列对。
-Unify(别名-Merge)参数定义了如何相对于不相关的公共属性统一左对象和右对象。可以辨别(<String>[,<String>])或合并(<ScriptBlock>)公共属性。默认情况下,将使用表达式合并不相关的公共属性:{$LeftOrVoid.$_, $RightOrVoid.$_}
<String>[,<String>]如果值不是ScriptBlock,则假定它是一个字符串数组,其中包含一个或两个定义左右键格式的项。如果项目包含星号(*),星号将替换为属性名称,否则项目将用作属性名称的前缀。
注意:如果已使用,则会自动将连续数字添加到公用属性名称中。
...

示例:

$Csv1 = ConvertFrom-Csv 'Server,Info
server1,item1
server1,item1'

$Csv2 = ConvertFrom-Csv 'Server,Info
server2,item2
server2,item2'

$Csv1 | Join $Csv2 -Unify *1, *2

结果:

Server1 Server2 Info1 Info2
------- ------- ----- -----
server1 server2 item1 item2
server1 server2 item1 item2

相关问题