我有一个包含所有历史数据的文本文件。从第二天开始,我开始接收增量文件,这些文件可以包含新记录以及历史文件中的更新记录。
我想说我有历史数据:
ID|NAME|COUNTRY
----------
1|BRAD PITT|USA
2|GEORGE CLOONEY|USA
3|RAJESH KHANNA|INDIA
第二天我收到了一个文件
ID|NAME|COUNTRY
----------
1|BRAD PITT|CANADA
4|DANIEL RADCLIFFE|UK
我想用
创建一个新文件ID|NAME|COUNTRY
----------
1|BRAD PITT|CANADA
2|GEORGE CLOONEY|USA
3|RAJESH KHANNA|INDIA
4|DANIEL RADCLIFFE|UK
ID是这里的关键,分隔符是常量的文件。
使用任何数据库工具都可以轻松实现,但遗憾的是我的新工作需要使用Scripting(Perl / Powershell)实现,我不太擅长。
我感谢任何帮助。
答案 0 :(得分:2)
如果您想使用PowerShell完成此任务 - 当您收到新文件时,可以使用Import-Csv
轻松解析新数据文件:
$NewData = Import-Csv -Path '.\incomingFile' -Delimiter '|' -Header ID,Name,Country
$NewData
现在是一个对象数组,所有对象都有3个名为ID,Name和Country的属性,其中包含文件中的值。
假设原始文件(您要保持更新的文件)以相同格式保存,您也希望使用相同的技术将该文件读入内存
找到需要更新的行的最快方法是,使用hashtable
属性作为键,将持久文件中的所有行放入ID
:
$OriginalDataTable = @{}
$OriginalData = Import-Csv -Path '.\originalFile' -Delimiter '|'
$OriginalData |ForEach-Object {
$OriginalDataTable[$_.ID] = $_
}
现在,您可以使用相同的方法循环遍历$NewData
数组,并将值分配给哈希表中与原始数据相对应的正确ID
- 如果该行已存在,则会被覆盖,否则它会被添加:
$NewData |ForEach-Object {
$OriginalDataTable[$_.ID] = $_
}
然后最后按ID
对值进行排序,并将它们导出回文件:
$OriginalDataTable.Keys |Sort-Object |ForEach-Object {
$OriginalDataTable[$_]
} |Export-Csv -Path '.\updatedFile' -Delimiter '|' -NoTypeInformation
答案 1 :(得分:1)
自从我写perl以来已经很长时间了,但这是一门非常容易学习的语言。
您想要做的基本知识是:
加载原始数据
使用新数据更新原始数据
写出新文件
这样做的代码如下,但绝对应该重构以满足您的直接需求,如果我们查看大文件,这不是一个很好的例子。
#!/usr/bin/perl
use strict;
use warnings;
my $handle;
my @lines;
my $line;
my @file_data = ();
my @columns = ();
open $handle, '<', "/tmp/sample.txt";
chomp(@lines = <$handle>);
close $handle;
# remove header
shift @lines;
shift @lines;
foreach $line (@lines){
@columns = split("|",$line);
@file_data[$columns[0]] = $line;
}
open $handle, '<', "/tmp/updated.txt";
chomp(@lines = <$handle>);
close $handle;
# remove header
shift @lines;
shift @lines;
foreach $line (@lines){
@columns = split("|",$line);
@file_data[$columns[0]] = $line;
}
# remove blank line
shift @file_data;
open $handle, '>', "/tmp/combined.txt";
print $handle join("\n",@file_data);
close $handle;