我有一个文件如下: FILE1.TXT
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ
1 299 309 DDD A@ZZZ 345
1 299 309 DDD A@ZZZ 678
如果第5列相同,我试图合并第6列。 输出应为:
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678
因此,如果第5列相同,则第6列应该相同。
我正在尝试使我丢失数据,因为如果第6列为空则不会保留该行:
perl -lane 'if($.==1){@a=@F;next} if($F[4]eq$a[4]){$a[5].=";$F[5]";}else{for($i=0;$i<@a;$i++){printf "\t%s",$a[$i]};print"";@a=@F}
END{for($i=0;$i<@a;$i++){printf "\t%s",$a[$i]};print""}' file1.txt
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234;
1 299 309 DDD A@ZZZ 345;678
如何保留所有行?
答案 0 :(得分:2)
另一个awk
,不改变输入间距
$ awk 'NR==FNR {a[$5]=$5 in a?a[$5] ($6==""?"":","$6):$0; next}
{print a[$5]}' file{,}
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 298 306 CCC A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678
答案 1 :(得分:1)
关注awk
可能对您有帮助。
awk 'FNR==NR{a[$5]=a[$5] && $NF~/[0-9]+/?a[$5]","$NF:($NF~/[0-9]+/?$NF:a[$5]);next} {$NF=$5 in a?$NF!~/[0-9]+/?$5 FS a[$5]:a[$5]:$5;} 1' Input_file Input_file
编辑: 现在添加一种非单一形式的解决方案。这里也会很快添加解释。
awk '
FNR==NR{
a[$5]=a[$5] && $NF~/[0-9]+/?a[$5]","$NF:($NF~/[0-9]+/?$NF:a[$5]);
next
}
{
$NF=$5 in a?$NF!~/[0-9]+/?$5 FS a[$5]:a[$5]:$5;
}
1
' Input_file Input_file
输出如下。
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678
答案 2 :(得分:1)
awk 'FNR==NR{
if($6!="")
a[$5]=($5 in a ? a[$5] ",":"")$6;
next
}
{
$6=a[$5]
}1' infile infile
测试结果:
$ cat f
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ
1 299 309 DDD A@ZZZ 345
1 299 309 DDD A@ZZZ 678
$ awk 'FNR==NR{if($6!="")a[$5]=($5 in a ? a[$5] ",":"")$6;next}{$6=a[$5]}1' f f
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678
答案 3 :(得分:1)
它标记为perl,所以我觉得我们需要一个perl答案:
#!/usr/bin/env perl
use strict;
use warnings;
#read all the rows from STDIN or specified file into an array of arrays.
my @rows = map { [split] } <>;
#define a hash to look for lines with matching keys.
my %value_lookup;
#iterate the rows.
foreach my $row ( @rows ) {
#check if there's a '6th field' (one of the examples is blank)
if ( $row -> [5] ) {
#push it into a lookup list if there is one. (might only be one element for non dupes.
push ( @{$value_lookup{$row -> [4]}}, $row -> [5]);
}
}
#iterate each row, replacing the 6th element (index 5)
#with whatever is in the value lookup above.
#or blank, if relevant.
foreach my $row ( @rows ) {
$row -> [5] = join ( ",", @{$value_lookup{$row->[4]}});
#print output, tab separated.
print join ("\t", @$row ),"\n";
}
这是一个更详尽的解决方案,因为它适用于任何线路排序。如果你可以依赖它只是连续的线被合并,它会有所简化。
根据您的输入,这会给出:
1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678