CMD or Powershell command to combine (merge) corresponding lines from two files

前端 未结 6 1684
说谎
说谎 2020-11-29 12:56

Is it possible using CMD and Powershell to combine 2 files into 1 file like this:

file1-line1 tab file2-line1
file1-line2 tab file2-line2
file1-line3 tab file2-li         


        
6条回答
  •  清歌不尽
    2020-11-29 13:30

    A generalized solution supporting multiple files, building on Ansgar Wiechers' great, memory-efficient System.IO.StreamReader solution:

    PowerShell's ability to invoke members (properties, methods) directly on a collection and have them automatically invoked on all items in the collection (member enumeration, v3+) allows for easy generalization:

    # Make sure .NET has the same current dir. as PS.
    [System.IO.Directory]::SetCurrentDirectory($PWD)
    
    # The input file paths.
    $files = 'file1', 'file2', 'file3'
    
    # Create stream-reader objects for all input files.
    $readers = [IO.StreamReader[]] $files
    
    # Keep reading while at least 1 file still has more lines.
    while ($readers.EndOfStream -contains $false) {
    
      # Read the next line from each stream (file).
      # Streams that are already at EOF fortunately just return "".
      $lines = $readers.ReadLine()
    
      # Output the lines separated with tabs.
      $lines -join "`t"
    
    }
    
    # Close the stream readers.
    $readers.Close()
    

    Get-MergedLines (source code below; invoke with -? for help) wraps the functionality in a function that:

    • accepts a variable number of filenames - both as an argument and via the pipeline

    • uses a configurable separator to join the lines (defaults to a tab)

    • allows trimming trailing separator instances

    function Get-MergedLines() {
    <#
    .SYNOPSIS
    Merges lines from 2 or more files with a specifiable separator (default is tab).
    
    .EXAMPLE
    > Get-MergedLines file1, file2 '<->'
    
    .EXAMPLE
    > Get-ChildItem file? | Get-MergedLines
    #>
      param(
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('PSPath')]
        [string[]] $Path,
    
        [string] $Separator = "`t",
    
        [switch] $TrimTrailingSeparators
      )
    
      begin { $allPaths = @() }
    
      process { $allPaths += $Path }
    
      end {
    
        # Resolve all paths to full paths, which may include wildcard resolution.
        # Note: By using full paths, we needn't worry about .NET's current dir.
        #       potentially being different.
        $fullPaths = (Resolve-Path $allPaths).ProviderPath
    
        # Create stream-reader objects for all input files.
        $readers = [System.IO.StreamReader[]] $fullPaths
    
        # Keep reading while at least 1 file still has more lines.
        while ($readers.EndOfStream -contains $false) {
    
          # Read the next line from each stream (file).
          # Streams that are already at EOF fortunately just return "".
          $lines = $readers.ReadLine()
    
          # Join the lines.
          $mergedLine = $lines -join $Separator
    
          # Trim (remove) trailing separators, if requested.
          if ($TrimTrailingSeparators) {
            $mergedLine = $mergedLine -replace ('^(.*?)(?:' + [regex]::Escape($Separator) + ')+$'), '$1'
          }
    
          # Output the merged line.
          $mergedLine
    
        }
    
        # Close the stream readers.
        $readers.Close()
    
      }
    
    }
    

提交回复
热议问题