Perl解决方案:

Perl解决方案:

这是两个常见的分隔文本文件转换问题,我想找到脚本来处理(我不知道是否awkperl适合这些任务)。

csh是我的 Solaris 10 unix 服务器上的默认 shell,因此适用于 或cshshell的解决方案sh将是首选。

问题一:

我有以下 2 个分隔的 ASCII 文件:File1.datFile2.dat

File1.dat(地图文件):

1|A  
2|B  
3|C  
4|D  
5|E  
6|F  
.  
.  
.  
26|Z  
27|Who  
28|What  
29|Where

文件2.dat

Field1|Field2|Field3  
1|John|20120101  
3|Amy|20120103  
6|Larry|20120104  
3|Kevin|20120203  
8|Fred|20120623  
4|Mary|20120728  
26|Eric|20120819  
28|Larry|20120917

我想使用中表示的地图File1.dat转换为如下所示的File2.dat第三个文件。File3.dat本质上,我使用 File1.dat 中的映射在我的文件中创建/填充一个新列,以便最后,新转换的文件有 4 列,如下所示:

文件3.dat

Field1|Field2|Field3|Field4  
1|A|John|20120101  
3|C|Amy|20120103  
6|F|Larry|20120104  
3|C|Kevin|20120203  
8|H|Fred|20120623  
4|D|Mary|20120728  
26|Z|Eric|20120819  
28|What|Larry|20120917

问题2:

我只想保留具有以下共性的记录系列的第一个记录(在一系列排序的记录中)[字段 2、字段 3、字段 4 在记录中具有相同的值]

我有以下初始分隔文件 File1.dat(15 条记录,每条记录有 4 个字段)。左侧不是文件的一部分,它只是一个记录#,因此我们可以跟踪正在发生的情况。

文件1.dat

    Field1|Field2|Field3|Field4
1.    20120227|Andy|101|34  
2.    20120315|Andy|101|34  
3.    20120415|Andy|101|36  
4.    20120417|Andy|103|37  
5.    20120417|Andy|103|37  
6.    20120227|Jane|101|34  
7.    20120315|Jane|101|34  
8.    20120415|Jane|101|36  
9.    20120417|Jane|103|37  
10.   20120417|Jane|103|37  
11.   20120227|Bob|101|34  
12.   20120315|Bob|101|34  
13.   20120415|Bob|101|36  
14.   20120417|Bob|103|37  
15.   20120417|Bob|103|37

我想将这个包含 15 条记录的文件 () 转换为如下所示的File1.dat新文件 ( )(仅保留这 9 条记录)。File2.dat

正如您所看到的,它取出了 中的重复记录File1.dat,其中重复记录的定义等于 [ Field2 & Field3 & Field4 在任何 2 个或更多记录中具有相同的值 ]。

文件2.dat

1.   20120227|Andy|101|34
3.   20120415|Andy|101|36
4.   20120417|Andy|103|37
6.   20120227|Jane|101|34
8.   20120415|Jane|101|36
9.   20120417|Jane|103|37
11.  20120227|Bob|101|34
13.  20120415|Bob|101|36
14.  20120417|Bob|103|37

结论:

请让我知道解决方案代码中的何处解决了以下两件事:

a) 我的文件中的分隔符是管道|字符
b) 代码的哪一部分引用了 Field1、Field2、Field3、Field4 等

答案1

Perl解决方案:

问题1。

File1.dat 被读入哈希,第一列是键,第二列是值。然后,处理 File2.dat,并根据从第一列(在 Perl 中为第零列)获取的键将散列中的值插入表示一行上的值的数组中。

#!/usr/bin/perl
use warnings;
use strict;

my %tab;

open my $F1, '<', 'File1.dat' or die $!;
while (<$F1>) {
    chomp;
    my ($key, $value) = split /\|/; # Here, the delimiter is mentioned.
    $tab{$key} = $value;
}

open my $F2, '<', 'File2.dat' or die $!;
while (<$F2>) {
    chomp;
    my @cols = split /\|/;
    splice @cols, 1, 0, $tab{$cols[0]};
    print join('|', @cols), "\n";
}

您可以使用标准实用程序获得类似的输出:

join -a2 -t'|' <(sort File1.dat) <(sort File2.dat) | sort -n

问题2。

记住您在哈希中已经看到的字段组合。如果组合是新的,则打印该行,否则不执行任何操作。

#!/usr/bin/perl
use warnings;
use strict;
use feature 'say';

my %seen;
while (<>) {
    chomp;
    my @fields = split /\|/, $_, 2;          # Only split into 2 fields.
    say unless exists $seen{$fields[1]};     # Do not print if already seen.
    undef $seen{$fields[1]};                 # Mark the key as seen.
}

相关内容