【问题标题】:How create combined file from two text files in powershell?如何从powershell中的两个文本文件创建组合文件?
【发布时间】:2021-08-18 01:01:57
【问题描述】:

如何使用来自两个不同文本文件的组合行创建文件并创建像这样的新文件:

First line from text file A
First line from text file B
Second line from text file A
Second line from text file B
...

【问题讨论】:

    标签: powershell merge file-io interleave


    【解决方案1】:

    对于一个解决方案:

    • 保持内存使用不变(不会预先将整个文件加载到内存中)
    • 处理较大的文件时可以接受。

    需要直接使用 .NET API

    # Input files, assumed to be in the current directory.
    # Important: always use FULL paths when calling .nET methods.
    $dir = $PWD.ProviderPath
    $fileA = [System.IO.File]::ReadLines("dir/fileA.txt")
    $fileB = [System.IO.File]::ReadLines("$dir/fileB.txt")
    
    # Create the output file.
    $fileOut = [System.IO.File]::CreateText("$dir/merged.txt")
    
    # Iterate over the files' lines in tandem, and write each pair
    # to the output file.
    while ($fileA.MoveNext(), $fileB.MoveNext() -contains $true) {
      if ($null -ne $fileA.Current) { $fileOut.WriteLine($fileA.Current) }
      if ($null -ne $fileB.Current) { $fileOut.WriteLine($fileB.Current) }
    }
    
    # Dipose of (close) the files.
    $fileA.Dispose(); $fileB.Dispose(); $fileOut.Dispose()
    

    注意:.NET API 默认使用 UTF-8,但如果需要,您可以传递所需的编码。

    另请参阅:相关的 .NET API 帮助主题:


    仅使用 PowerShell 功能的解决方案:

    • 注意:使用仅限 PowerShell 的功能,您一次只能懒惰地枚举 一个 文件的行,因此需要将另一个完全读入内存。 (但是,您可以再次通过 .NET API 使用惰性可枚举,即 System.IO.File]::ReadLines(),如上所示,或者将 both 文件全部读入内存。)

    • 可接受性能的关键是只有 one Set-Content 调用(可能还有 one Add-Content 调用)处理所有输出线。

      • 但是,考虑到 Get-Content(没有 -Raw)本身非常慢,由于使用附加属性装饰读取的每一行,基于 .NET API 的解决方案的性能会明显更好
    # Read the 2nd file into an array of lines up front.
    # Note: -ReadCount 0 greatly speeds up reading, by returning
    #       the lines directly as a single array.
    $fileBLines = Get-Content fileB.txt -ReadCount 0 
    
    $i = 0 # Initialize the index into array $fileBLines.
    
    # Lazily enumerate the lines of file A.
    Get-Content fileA.txt | ForEach-Object {
      $_ # Output the line from file A.
      # If file B hasn't run out of lines yet, output the corresponding file B line.
      if ($i -lt $fileBLines.Count) { $fileBLines[$i++] }
    } | Set-Content Merged.txt
    
    # If file B still has lines left, append them now:
    if ($i -lt $fileBLines.Count) {
      Add-Content Merged.txt -Value $fileBLines[$i..($fileBLines.Count-1)]
    }
    

    注意:Windows PowerShellSet-Content cmdlet 默认为“ANSI”编码,而 PowerShell (Core) (v6+) 使用 BOM-less UTF-8;根据需要使用-Encoding 参数。

    【讨论】:

      【解决方案2】:
      $file1content = Get-Content -Path "IN_1.txt"
      $file2content = Get-Content -Path "IN_2.txt"
      
      $filesLenght =@($file1content.Length, $file2content.Length)
      
      for ($i = 1; $i -le ($filesLenght | Measure-Object -Maximum).Maximum; $i++)
      {   Add-Content -Path "OUT.txt" $file1content[$i]
          Add-Content -Path "OUT.txt" $file2content[$i]
      }
      

      【讨论】:

      • 这可行,但有两个缺点:首先将两个文件全部读入内存(尽管使用文本文件通常无关紧要)并且写入输出文件会很慢,因为@ 987654322@ 必须在每次迭代中打开和关闭文件(您可以通过在循环中只调用 一个 Add-Content 来缓解这个问题,但最好的解决方案是只使用一个 Set-Content作为附加管道段调用)。两个小问题:$i 必须以0 开头,而不是1。如果你使用Add-Content,你应该首先创建/截断输出文件。 /cc @AbrahamZinala
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2015-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多