2014-12-01 128 views
2

相应的线路是否有可能使用CMD和Powershell的2个文件合并成1个文件是这样的:CMD或powershell命令合并(合并)从两个文件

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

因此,需要文件1线1与插入一个选项卡,然后插入文件2行1.然后为每个文件中的所有后续行执行此操作?

回答

5

在PowerShell中,并假设这两个文件具有完全相同的行数:

$f1 = Get-Content file1 
$f2 = Get-Content file2 

for ($i = 0; $i -lt $f1.Length; ++$i) { 
    $f1[$i] + "`t" + $f2[$i] 
} 
+0

干得漂亮。值得注意的两件事:(a)该解决方案将两个文件作为一个整体(作为行数组)读入内存中,这对于大文件可能有问题。 (b)如果行数不同,行为也是合理的:在PowerShell中超出数组边界的索引产生'$ null';在字符串连接的上下文中,这相当于空字符串,所以一旦'file2'用尽了行,你就不会在''\ t''之后得到任何东西。 – mklement0 2017-04-28 19:32:40

1

Powershell的溶液:

$file1 = Get-Content file1 
$file2 = Get-Content file2 
$outfile = "file3.txt" 

for($i = 0; $i -lt $file1.length; $i++) { 
    "$($file1[$i])`t$($file2[$i])" | out-file $outfile -Append 
} 
+1

您的命令在'out-file'调用中的输出字符串之前缺少'-InputObject',因为该字符串被隐式地视为'-Encoding'参数。这就是说,除非你关心内存(在这种情况下'System.IO.StreamReader'解决方案可能是一个更好的选择),'$(for($ i = 0; $ i -lt $ file1.length; $($ i ++){“$($ file1 [$ i])\'t $($ file2 [$ i])”})| Out-File $ outfile '更简单,速度更快,并且不需要您事先确保预先存在的输出文件被截断。 – mklement0 2017-04-28 19:00:28

2
@echo off 
setlocal EnableDelayedExpansion 
rem Next line have a tab after the equal sign: 
set "TAB= " 
Rem First file is read with FOR /F command 
Rem Second file is read via Stdin 
< file2.txt (for /F "delims=" %%a in (file1.txt) do (
    Rem Read next line from file2.txt 
    set /P "line2=" 
    Rem Echo lines of both files separated by tab 
    echo %%a%TAB%!line2! 
)) 

进一步细节在this post

2

大概最简单的解决方案重要的是使用Linux paste实用程序的Windows端口(例如, paste.exeUnxUtils):

paste C:\path\to\file1.txt C:\path\to\file2.txt 

man page

说明由对应来自每个文件的行,由制表符分隔,到标准输出顺序的

写行。


对于一个PowerShell(ISH)的解决方案,我用两个​​:

$sr1 = New-Object IO.StreamReader 'C:\path\to\file1.txt' 
$sr2 = New-Object IO.StreamReader 'C:\path\to\file2.txt' 

while ($sr1.Peek() -ge 0 -or $sr2.Peek() -ge 0) { 
    if ($sr1.Peek() -ge 0) { $txt1 = $sr1.ReadLine() } else { $txt1 = '' } 
    if ($sr2.Peek() -ge 0) { $txt2 = $sr2.ReadLine() } else { $txt2 = '' } 

    "{0}`t{1}" -f $txt1, $txt2 
} 

这避免了将它们合并,负有前两个文件完全读入内存大文件内存耗尽的风险。

1

一个推广解决方案,支持多个文件,在Ansgar Wiechers' great, memory-efficient System.IO.StreamReader solution建设:

PowerShell的直接在集合调用成员(属性,方法),并让他们对集合中的所有项目自动调用能力(V3 + )可以很容易地推广:

# 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(下面源代码; invok e为-?用于帮助)包装在一个函数的功能是:

  • 接受可变数量的文件名的 - 都作为参数,并经由管道

  • 使用配置分离器加入行(默认为选项卡)

  • 允许修剪尾随分隔符实例

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() 

    } 

}