例如,有5个数字=> [1,2,3,4,5]和3组
File1中(组1):
1
3
5
文件2(第2组):
3
4
文件3(组3):
1
5
输出(第1列:是否在第1组,第2列:是否在第2组,第3列:是否在第3组[NA表示不是..]):
1 NA 1
3 3 NA
NA 4 NA
5 NA 5
或类似的东西(+表示, - 表示不是):
1 + - +
3 + + -
4 - + -
5 + - +
我尝试了join
和merge
,但看起来两者都不适用于多个文件..(例如,8个文件)
答案 0 :(得分:2)
你说数字是1-5,但据我所知,这与你想要的输出无关。您只能在输出中使用文件中找到的数字。此代码将执行您想要的操作:
use strict;
use warnings;
use feature 'say';
my @hashes;
my %seen;
local $/; # read entire file at once
while (<>) {
my @nums = split; # split file into elements
$seen{$_}++ for @nums; # dedupe elements
push @hashes, { map { $_ => $_ } @nums }; # map into hash
}
my @all = sort { $a <=> $b } keys %seen; # sort deduped elements
# my @all = 1 .. 5; # OR: provide hard-coded list
for my $num (@all) { # for all unique numbers
my @fields;
for my $href (@hashes) { # check each hash
push @fields, $href->{$num} // "NA"; # enter "NA" if not found
}
say join "\t", @fields; # print the fields
}
您可以使用@all
或任何其他有效列表替换my @all = 1 .. 5
中的已排序重复数据删除列表。然后,它将为这些数字添加行,并打印出缺失值的额外“NA”字段。
您还应该知道,这取决于您的文件内容是数字的事实,但仅限于@all
数组的排序,因此如果您将其替换为您自己的列表,或者您自己的排序例程,您可以使用任何值。
此脚本将采用任意数量的文件并对其进行处理。例如:
$ perl script.pl f1.txt f2.txt f3.txt
1 NA 1
3 3 NA
NA 4 NA
5 NA 5
感谢Brent Stewart了解OP意味着什么。
答案 1 :(得分:0)
对于两个文件,您可以轻松使用join
,如下所示(假设file1
和file2
已排序):
$ join -e NA -o 1.1,2.1 -a 1 -a 2 file1 file2
1 NA
3 3
NA 4
5 NA
如果你有两个以上的文件会变得更复杂。
这是一个强力grep
解决方案:
#!/bin/bash
files=(file1 file2 file3)
sort -nu "${files[@]}" | while read line; do
for f in "${files[@]}"; do
if grep -qFx "$line" "$f"; then
printf "${line}\t"
else
printf "NA\t"
fi
done
printf "\n"
done
输出:
1 NA 1
3 3 NA
NA 4 NA
5 NA 5
答案 2 :(得分:0)
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
my @lines;
my $filecount = 0;
# parse
for my $filename (@ARGV){
open my $fh, '<', $filename;
while( my $line = <$fh> ){
chomp($line);
next unless length $line;
$lines[$line][$filecount]++;
}
close $fh;
}continue{
$filecount++;
}
# print
for my $linenum ( 1..$#lines ){
my $line = $lines[$linenum];
next unless $line;
print ' ' x (5-length $linenum), $linenum, ' ';
for my $elem( @$line ){
print $elem ? 'X' : ' '
}
print "\n";
}
1 X X
3 XX
4 X
5 X X
答案 3 :(得分:0)
如果您的输入文件单调增加,并且只是在输入样本建议的每行上包含一个整数,您可以简单地预处理输入文件并使用粘贴:
for i in file{1,2,3}; do # List input files
awk '{ a += 1; while( $1 > a ) { print "NA"; a += 1 }} 1' $i > $i.out
done
paste file{1,2,3}.out
这会使某些列中的尾随条目为空。修复这是留给读者的练习。