使用perl或powershell中的增量文件更新记录

时间:2015-12-10 19:16:38

标签: perl powershell

我有一个包含所有历史数据的文本文件。从第二天开始,我开始接收增量文件,这些文件可以包含新记录以及历史文件中的更新记录。

我想说我有历史数据:

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)实现,我不太擅长。

我感谢任何帮助。

2 个答案:

答案 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以来已经很长时间了,但这是一门非常容易学习的语言。

您想要做的基本知识是:

  1. 加载原始数据

  2. 使用新数据更新原始数据

  3. 写出新文件

  4. 这样做的代码如下,但绝对应该重构以满足您的直接需求,如果我们查看大文件,这不是一个很好的例子。

    #!/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;