合并两个CSV,然后对输出中的列进行重新排序

时间:2019-02-26 10:13:31

标签: powershell csv

我有第一个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

如您所见,问题在于2个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'

2 个答案:

答案 0 :(得分:3)

您建议的内容不是很有用,甚至不是有效的CSV。恕我直言,只有两个结果才有意义:

此:

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,删除标题行中的数字,并将所有内容保存到文件中。

答案 1 :(得分:1)

由于似乎有几种用例来识别不相关的属性键而不是合并它们,所以我添加了一个新功能。 Join-Object cmdlet的-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