2012-07-23 83 views
0

对不起,如果这类问题一直在问,但我在搜索时找不到。比较2个文件并根据条件打印

我有两个文件A和B.我需要创建一个包含在一个格式的差异文件C如下图所示:

文件:

foo1 2.1 3 
foo2 3.1 3 
foo3 4.1 3 
foo4 2.1 3 
foo5 3.1 3 

文件B:

foo1 2.0 2.9 
foo2 2.1 3 
foo4 2.1 3 

文件C(OUTPUT):LHS包含来自文件A的值。RHS包含来自文件B的值(或只有xxxx,如果foo不存在)

2.1 3 foo1 2.0 2.9 
3.1 3 foo2 2.1 3 
4.1 3 foo3 xxxxxxxx 
2.1 3 foo4 2.1 3 
3.1 3 foo5 xxxxxxxx 
+0

你尝试过什么,什么是你有问题,这气味像功课 – 8bitwide 2012-07-23 22:45:32

+0

对不起,我只是改变了形式。我无法继续将任一类型的值放在同一行上 – user1497417 2012-07-23 22:47:33

+0

您能描述一下输出的格式应该是什么吗?目前还不清楚你要从你的例子中寻找什么。 – Blckknght 2012-07-23 22:48:04

回答

1

单程使用awk。保存第一个字段fileB作为散列的一个关键字,其余字段作为它的值,并且在fileA中的每一行进行比较,如果该关键字存在,则打印xxxxxxxx或散列值。

运行下一个命令:

awk ' 
    BEGIN { 
     OFS = "\t"; 
    } 

    FNR == NR { 
     b[ $1 ] = $2 "\t" $3; 
     next; 
    } 

    FNR < NR { 
     str = ($1 in b) ? b[ $1 ] : "xxxxxxxx"; 
     print $2, $3, $1, str; 
    } 
' fileB fileA 

随着下面的输出(制表符分隔的字段):

2.1  3  foo1 2.0  2.9 
3.1  3  foo2 2.1  3 
4.1  3  foo3 xxxxxxxx 
2.1  3  foo4 2.1  3 
3.1  3  foo5 xxxxxxxx 
+0

你击败了我35秒! +1 – Steve 2012-07-23 23:12:15

+0

完美,谢谢! – user1497417 2012-07-23 23:21:40

+0

@ user1497417:这应该是被接受的答案。 – Steve 2012-07-23 23:24:19

1

一种使用awk方式:

awk 'FNR==NR { array[$1]=$0; next; } { if ($1 in array) print $2, $3, array[$1]; else print $2, $3, $1, "xxxxxxxx"; }' fileB.txt fileA.txt 

在多行上分拆出:

FNR==NR { 
    array[$1]=$0 
    next 
} 

{ 
    if ($1 in array) { 
     print $2, $3, array[$1] 
    } 
    else { 
     print $2, $3, $1, "xxxxxxxx" 
    } 
} 

结果:

2.1 3 foo1 2.0 2.9 
3.1 3 foo2 2.1 3 
4.1 3 foo3 xxxxxxxx 
2.1 3 foo4 2.1 3 
3.1 3 foo5 xxxxxxxx 
+0

完美,谢谢! – user1497417 2012-07-23 23:21:59

+0

快速跟进 - 有没有办法在输出文件中对齐column3?假设我们有foo1,foo2,foobar3,fooo4等格式化会搞砸。 – user1497417 2012-07-24 00:02:22

+0

@ user1497417:请参阅上述Berei的回答和我的评论。 – Steve 2012-07-24 00:40:49

2

通读两个文件和将数据存储在由所述文件的第一fcolumn值键控的散列。

use strict; 
use warnings; 

my @files = qw/ FileA.txt FileB.txt /; 
my %data; 

for my $i (0, 1) { 

    open my $fh, '<', $files[$i] or die qq(Unable to open "$files[$i]": $!); 

    while (<$fh>) { 
    s/\s+$//; 
    my ($key, $val) = split ' ', $_, 2; 
    $data{$key}[$i] = $val; 
    } 
} 

for my $key (sort keys %data) { 
    printf "%s %s %s\n", 
     map $_ // 'xxxxxxxx', $data{$key}[0], $key, $data{$key}[1]; 
} 

输出

2.1 3 foo1 2.0 2.9 
3.1 3 foo2 2.1 3 
4.1 3 foo3 xxxxxxxx 
2.1 3 foo4 2.1 3 
3.1 3 foo5 xxxxxxxx 
+0

感谢您的帮助! – user1497417 2012-07-23 23:39:40