使用PowerShell

时间:2016-10-10 20:09:36

标签: powershell powershell-v2.0

我有2个文件,行数相同且顺序相同。

实施例

文字1:

1,MA,DC
2,NY,BC
3,CT,CD

文字2

,PRO,123
,PRO,ABC
,GRO,XYZ

输出应为:

1,MA,DC,PRO,123
2,NY,BC,PRO,ABC
3,CT,CD,GRO,XYZ

到目前为止,我尝试使用Join命令和add-content,但我在第一组的底部使用第二组。我只想尝试将线路连接成一条线路。 我也在考虑创建数据集和循环,但我认为在Shell中可能有一种更简单的方法,如 cat

3 个答案:

答案 0 :(得分:4)

将两个文件读入数组并将其压缩为常规for循环:

$File1 = Get-Content C:\path\to\file1.txt
$File2 = Get-Content C:\path\to\file2.txt

for($i = 0; $i -lt $File1.Count; $i++)
{
    ('{0}{1}' -f $File1[$i],$File2[$i]) |Add-Content C:\path\to\output.txt
}

答案 1 :(得分:4)

cat也不会给你。另外,我不太确定你的意思是“加入命令”。

尽管如此,这并不难。只需读取这两个文件,然后连接这些行:

$a = Get-Content text1
$b = Get-Content text2

0..[Math]::Max($a.Length, $b.Length) | ForEach-Object {
  $a[$_] + $b[$_]
}

Math.Max只是确保代码仍然有效,无论两个文件的行数是否相同。

答案 2 :(得分:1)

默认数组生成模式下的Get-Content非常慢,并且将文件的全部内容保存在内存中,这将无法使用大文件。其他答案需要10个100秒的4MB日志文件。

使用.NET类IO.StreamReader和IO.StreamWriter在 100毫秒内加入4MB文件
和2MB内100MB文件而不是分钟/小时。然而,仅在PS3.0及更新版本中才能看到如此出色的结果,而PS2使用的运行速度要慢得多(仍然比Get-Content快)。

function Join-FileLines (
    [ValidateScript({Test-Path -literal $_})] [string] $file1,
    [ValidateScript({Test-Path -literal $_})] [string] $file2,
    [ValidateScript({Test-Path -literal $_ -IsValid})] [string] $output
) {
    $a = New-Object IO.StreamReader $file1
    $b = New-Object IO.StreamReader $file2
    $c = New-Object IO.StreamWriter ($output,
                                     $false, # don't append
                                     [Text.Encoding]::UTF8)
    while (!$a.EndOfStream -or !$b.EndOfStream) {
        $c.WriteLine($a.ReadLine() + $b.ReadLine())
    }
    $a.Close()
    $b.Close()
    $c.Close()
}

一个多文件连接器:

function Join-FileLines(
    [ValidateScript({Test-Path -literal $_})] [string[]] $files,
    [ValidateScript({Test-Path -literal $_ -IsValid})] [string] $output
) {
    $streams = $files | ForEach { New-Object IO.StreamReader $_ }
    $streamOut = New-Object IO.StreamWriter ($output, $false, [Text.Encoding]::UTF8)
    while ($true) {
        $anyLeft = $false
        ForEach ($s in $streams) {
            $anyLeft = $anyLeft -or !$s.EndOfStream
            $streamOut.Write($s.ReadLine())
        }
        if (!$anyLeft) { break }
        $streamOut.WriteLine()
    }
    ForEach ($s in $streams) { $s.Close() }
    $streamOut.Close()
}