如何使用Perl整理和汇总文件中的记录?

时间:2009-05-05 12:50:53

标签: perl sed awk unix

我有一个以下格式的文本文件:

211B1 CUSTOMER|UPDATE|  
211B2 CUSTOMER|UPDATE|  
211B3 CUSTOMER|UPDATE|  
211B4 CUSTOMER|UPDATE|  
211B5 CUSTOMER|UPDATE|  
567FR CUSTOMER|DELETE|  
647GI CUSTOMER|DELETE|  

我想要一个处理文本文件并报告以下内容的脚本:

  • “更新”,找到了Acct的列CUSTOMER:211B1,211B2,211B3,211B4,211B5
  • 为“帐户”找到的CUSTOMER列“DELETE”:5675FR,6470GI

我可以编写简单的解决方案,但这对我来说似乎有点复杂,并希望得到帮助或指导。

5 个答案:

答案 0 :(得分:6)

collat​​e.pl

#!/usr/bin/perl

use strict;

my %actions;
while (<>) {
    my ($key, $fld, $action) = /^(\w+) (.+?)\|(.+?)\|/ or die "Failed on line $.!";
    push @{$actions{$action}{$fld}}, $key;
}

foreach my $action (keys %actions) {
    foreach my $fld (keys %{$actions{$action}}) {
        print "\"$action\" for column $fld found for Acct's: " . join(",", @{$actions{$action}{$fld}}), "\n";
    }
}

像这样使用:

perl collate.pl < input.txt > output.txt

答案 1 :(得分:1)

使用awk:

echo '211B1 CUSTOMER|UPDATE|  
211B2 CUSTOMER|UPDATE|  
211B3 CUSTOMER|UPDATE|  
211B4 CUSTOMER|UPDATE|  
211B5 CUSTOMER|UPDATE|  
567FR CUSTOMER|DELETE|  
647GI CUSTOMER|DELETE|' | awk -F '[ |]' '
    BEGIN {
        upd="";del=""
    } {
      if ($3 == "UPDATE") {upd = upd" "$1};
      if ($3 == "DELETE") {del = del" "$1};
    } END {
        print "Updates:"upd; print "Deletes:"del
    }'

产生

Updates: 211B1 211B2 211B3 211B4 211B5
Deletes: 567FR 647GI

它基本上只是将每一行分成三个字段(使用-F选项)并维护它附加的更新和删除列表,具体取决于“命令”。

BEGINEND在所有行处理之前和之后运行,因此它们是初始化和最终输出。

我将它放入脚本中以使其更容易。我把它作为一个命令行工具,因为我通常调试我的awk脚本。

答案 2 :(得分:1)

#!/usr/bin/perl

use strict;
use warnings;

my %data;

while ( my $line = <DATA> ) {
    next unless $line =~ /\S/;
    my ($acct, $col, $action) = split /\s|\|/, $line;
    push @{ $data{$action}->{$col} }, $acct;
}

for my $action ( keys %data ) {
    for my $col ( keys %{ $data{$action} } ) {
        print qq{"$action" for column $col found for acct's: },
              join q{,}, @{ $data{$action}->{$col} }, "\n";    
    }

}
__DATA__
211B1 CUSTOMER|UPDATE|  
211B2 CUSTOMER|UPDATE|  
211B3 CUSTOMER|UPDATE|  
211B4 CUSTOMER|UPDATE|  
211B5 CUSTOMER|UPDATE|  
567FR CUSTOMER|DELETE|  
647GI CUSTOMER|DELETE|

答案 3 :(得分:0)

另一个awk版本,虽然代码值的顺序颠倒了,并且在每行的末尾都有一个额外的“,”


BEGIN { FS="[ |]" }

{
        key = $3 " for column " $2
        MAP[ key ] = $1 "," MAP[ key ]
}

END {
        for ( item in MAP ) {
                print item " found for Acct's: " MAP[ item ]
        }
}

答案 4 :(得分:-2)

根据您的问题,您可以这样做:

perl -i.bak -pe'if(/^211B[1-5]/){s/CUSTOMER/UPDATE/}elsif(/^(5675FR|6470GI)/){s/CUSTOMER/DELETE/}' filename

虽然我现在注意到示例中最后两个帐号不同,而且第二列已经有了这些值......