使用 PowerShell 在同一行加入两个文件行
Join two files lines in the same line with PowerShell
我有 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
到目前为止,我尝试使用加入命令和添加内容,但我在第一组的底部得到了第二组。我只是想将多行合并为一行。
我也在考虑创建数据集和循环,但我认为可能有更简单的方法,例如 Shell 中的 cat。
将两个文件读入数组并在常规 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
}
cat
也不会给你。另外我不太清楚你所说的 "join command".
是什么意思
不过,这并不难。只需阅读这两个文件,然后连接以下行:
$a = Get-Content text1
$b = Get-Content text2
0..[Math]::Max($a.Length, $b.Length) | ForEach-Object {
$a[$_] + $b[$_]
}
Math.Max
只是确保代码仍然有效,无论两个文件的行数是否相同。
Get-Content 在默认的数组生成模式下非常慢,并且将文件的全部内容保存在内存中,这不适用于大文件。其他答案需要 10 秒和 100 秒在一个 4MB 的日志文件上,有 100k 行。
使用 .NET 类 IO.StreamReader 和 IO.StreamWriter 在 100 毫秒内加入 4MB 文件
和 100MB 文件在 2 秒内而不是 minutes/hours。然而,只有 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()
}
我有 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
到目前为止,我尝试使用加入命令和添加内容,但我在第一组的底部得到了第二组。我只是想将多行合并为一行。 我也在考虑创建数据集和循环,但我认为可能有更简单的方法,例如 Shell 中的 cat。
将两个文件读入数组并在常规 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
}
cat
也不会给你。另外我不太清楚你所说的 "join command".
不过,这并不难。只需阅读这两个文件,然后连接以下行:
$a = Get-Content text1
$b = Get-Content text2
0..[Math]::Max($a.Length, $b.Length) | ForEach-Object {
$a[$_] + $b[$_]
}
Math.Max
只是确保代码仍然有效,无论两个文件的行数是否相同。
Get-Content 在默认的数组生成模式下非常慢,并且将文件的全部内容保存在内存中,这不适用于大文件。其他答案需要 10 秒和 100 秒在一个 4MB 的日志文件上,有 100k 行。
使用 .NET 类 IO.StreamReader 和 IO.StreamWriter 在 100 毫秒内加入 4MB 文件
和 100MB 文件在 2 秒内而不是 minutes/hours。然而,只有 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()
}