【问题标题】:Converting at least two text files with different rows into one csv - powershell将至少两个具有不同行的文本文件转换为一个 csv - powershell
【发布时间】:2020-04-10 14:03:07
【问题描述】:

我正在尝试使用 powershell 脚本将两个 TXT 文件转换为一个 CSV 文件。当文件具有相同的结构和相同的行数时,案例看起来很容易。但在我的情况下,txt 文件具有不同的结构。

两个 txt 文件中的管道符号不是分隔符,应视为普通字符,它是一个字符串。

文件 URL.txt

L5020|http://linktosite.de|URL
L100|http://sitelink.de|URL
L50|http://abcde.de|URL
L511|http://bbcccddeee.de|URL
L300|http://link123456.de|URL
L5450|http://randomlink.de|URL_DE
L5460|http://randomwebsitelink.de|URL_DE

文件 URL1.txt

L5020|http://linktosite.de|URL|P555
L100|http://sitelink.de|URL|P523
L50|http://abcde.de|URL|P53
L511|http://bbcccddeee.de|URL|P540

我期望的 CSV 应该如下所示,分隔符是“;”

HEADER1;HEADER2
L5020|http://linktosite.de|URL;L5020|http://linktosite.de|URL|P555
L100|http://sitelink.de|URL;L100|http://sitelink.de|URL|P523
L50|http://abcde.de|URL;L50|http://abcde.de|URL|P53
L511|http://bbcccddeee.de|URL;L511|http://bbcccddeee.de|URL|P540
L300|http://link123456.de|URL;  
L5450|http://randomlink.de|URL_DE;  
L5460|http://randomwebsitelink.de|URL_DE;   

我尝试过类似的方法

$URL = "C:\Users\XXX\Desktop\URL.txt"
$URLcontent = Get-Content $URL
$URL1 = "C:\Users\XXX\Desktop\URL1.txt"
$URLcontent1 = Get-Content $URL1

$results = @() # Empty array to store new created rows in
$csv = Import-CSV "C:\Users\XXX\Desktop\map.csv" -Delimiter ';'
foreach ($row in $csv) {
    $properties = [ordered]@{
        HEADER1   =  $URLcontent
        HEADER2    = $URLcontent1

          }
    # insert the new row as an object into the results-array
    $results += New-Object psobject -Property $properties
}
# foreach-loop filled the results-array - export it as a CSV-file
$results | Export-Csv "C:\Users\XXXX\Desktop\map_final.csv" -NoTypeInformation

还有类似的:

import-csv URL.txt -Header 'HEADER1' |  Export-CSV "C:\Users\xxx\Desktop\URL.csv"  -Delimiter ';' -NoTypeInformation 
import-csv URL1.txt  -Header 'HEADER2' | Export-CSV "C:\Users\xxx\Desktop\URL1.csv" -Delimiter ';' -NoTypeInformation  
Get-ChildItem "C:\Users\xx\Desktop" -Filter "URL*.csv" | Select-Object -ExpandProperty FullName | Import-Csv | Export-Csv .\combinedcsvs.csv -NoTypeInformation -Append

没有任何成功...

BR

【问题讨论】:

  • 我不懂组合逻辑。你能再澄清一点吗?在这里也显示预期的输出可能更容易。
  • 如果我错了,请纠正我,但是,你的最终产品是一个 csv,它具有从 txt 值中获取的多 1 个属性,如果 1 的大小比另一个大,它应该用空行填充它,它是可行的,但您能否详细说明答案,添加您尝试过的内容以及具有预期输出的文本文件?
  • 请说明您希望这两个文件在合并后的外观。
  • 使用这个Join-ObjectConvertFrom-Csv .\File1.txt -Header A | LeftJoin (ConvertFrom-Csv .\File2.txt -Header B,C,D -Delimiter '|')

标签: powershell


【解决方案1】:

根据您问题中的更新,如果您想自己构建一些东西,您可能想做这样的事情:

$Url1 = @(Get-Content .\URL1.txt)
$i = 0
Get-Content .\URL.txt | Foreach-Object {
    [pscustomobject]@{
        HEADER1 = $_
        HEADER2 = If ($i -lt $URL1.Count) { $URL1[$i++] }
    }
} | Export-Csv .\combinedcsvs.csv -Delimiter ';' -NoTypeInformation -Append

如果您不想经历重新发明轮子的麻烦(包括性能调整在内的所有陷阱)。使用我在评论中提到的Join-Object

Import-Csv .\URL.txt -Header HEADER1 |
LeftJoin (Import-Csv .\URL1.txt -Header HEADER2) |
Export-Csv .\combinedcsvs.csv -Delimiter ';' -NoTypeInformation -Append
  • 注意 1:我不知道你为什么要导入像 map.csv 这样的东西,我认为这是必需的。
  • 注意2:如果你还想走自己的路,试试avoid using the increase assignment operator (+=) to create a collection,这是一个非常昂贵的运营商。
  • 注意 3: 在行索引上连接行通常不是一个好主意,因为列表可能没有排序或有重复,因此最好在特定属性,例如 Url:

 

Import-Csv .\URL.txt -Delimiter '|' -Header Lid,Url,Type |
LeftJoin (Import-Csv .\URL1.txt -Delimiter '|' -Header Lid2,Url,Type2,Pid) -On Url |
Format-Table # or: Export-Csv .\combinedcsvs.csv -Delimiter ';' -NoTypeInformation

Lid   Url                         Type   Lid2  Type2 Pid
---   ---                         ----   ----  ----- ---
L5020 http://linktosite.de        URL    L5020 URL   P555
L100  http://sitelink.de          URL    L100  URL   P523
L50   http://abcde.de             URL    L50   URL   P53
L511  http://bbcccddeee.de        URL    L511  URL   P540
L300  http://link123456.de        URL
L5450 http://randomlink.de        URL_DE
L5460 http://randomwebsitelink.de URL_DE

或者在所有三个(LidUrlType)属性上:

Import-Csv .\URL.txt -Delimiter '|' -Header Lid,Url,Type |
LeftJoin (Import-Csv .\URL1.txt -Delimiter '|' -Header Lid,Url,Type,Pid) -On Lid,Url,Type |
Format-Table # or: Export-Csv .\combinedcsvs.csv -Delimiter ';' -NoTypeInformation

Lid   Url                         Type   Pid
---   ---                         ----   ---
L5020 http://linktosite.de        URL    P555
L100  http://sitelink.de          URL    P523
L50   http://abcde.de             URL    P53
L511  http://bbcccddeee.de        URL    P540
L300  http://link123456.de        URL
L5450 http://randomlink.de        URL_DE
L5460 http://randomwebsitelink.de URL_DE

【讨论】:

  • 嗨,正如我提到的“|”这里不是分隔符:)
  • 第一个示例使用与您的问题中给出的完全相同的输入文件产生与您的期望完全相同的输出。后面两个推荐的示例,将-Delimiter '|' 用于您的输入 文件,这些文件在给定的输入示例中清楚地显示了一个管道 (|) 符号。
  • 我已经更新了答案,并在顶部添加了一个小的特定脚本,您也可以在不使用 Join-Object cmdlet 的情况下执行此操作。
【解决方案2】:

如果您只想合并两个文件都包含数据的行,您可以执行以下操作:

$f1 = Get-Content file1.txt
$f2 = Get-Content file2.txt
$output = for ($i = 0; $i -lt [math]::Min($f1.count,$f2.count); $i++) {
   $f2[$i],$f1[$i] -join '|'
}
$output | Set-Content newfile.txt

如果您想合并所有重合的行并从其中一个文件中添加额外的行,您可以执行以下操作:

$output = for ($i = 0; $i -lt [math]::Max($f1.count,$f2.count); $i++) {
    if ($f1[$i] -and $f2[$i]) {
        $f2[$i],$f1[$i] -join '|'
    } 
    else {
        $f2[$i],$f1[$i] | Where {$_}
    }
}
$output | Set-Content newfile.txt

【讨论】:

  • 您好,抱歉,这不是我所期望的,结果应该是包含两个 txt 文件的 CSV(不是 txt)。左列来自一个文件的数据,右列来自第二个文件的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 2020-10-23
  • 1970-01-01
  • 2020-04-04
  • 2021-12-17
  • 1970-01-01
  • 2016-02-09
相关资源
最近更新 更多