我是unix的新手。我有tab delim txt文件,如下所示:
ID Region Strt End Length
sd_2_1 head 241 930 689
sd_2_1 trunk 16 240 224
sd_2_1 tail 1 15 14
sd_2_1 head 1 1 0
sd_2_1 trunk 2 832 830
sd_2_1 tail 833 930 97
sd_2_1 head 780 930 150
sd_2_1 trunk 663 779 116
sd_2_1 tail 1 662 661
sd_3_1 head 1020 1649 629
sd_3_1 trunk 783 1019 236
sd_3_1 tail 1 782 781
sd_3_1 trunk 1 1470 1469
sd_3_1 tail 1471 1649 178
sd_4_1 head 2 50 48
sd_4_1 trunk 51 701 650
sd_4_1 head 1 40 38
sd_4_1 trunk 41 101 60
sd_4_1 tail 102 122 20
具有不同条目(由空格分隔)的每个Id多个区域子集我想要将每个ID与其自己的子集进行比较,并且仅保留每个具有最大干线长度的ID的子集。最后我想获得如下文件:
ID Region Strt End Length
sd_2_1 head 1 1 0
sd_2_1 trunk 2 832 830
sd_2_1 tail 833 930 97
sd_3_1 trunk 1 1470 1469
sd_3_1 tail 1471 1649 178
sd_4_1 head 2 50 48
sd_4_1 trunk 51 701 650
任何帮助都将受到高度赞赏。请指导我
答案 0 :(得分:3)
awk
救援!
$ (head -1 file && sed 1d file
| awk -v RS= '{len=0;
for(i=2;i<=NF;i+=5)
if($i=="trunk") {len=$(i+3); break}
if(len>v[$1]) {v[$1]=len; r[$1]=$0}
}
END{for(k in r) print r[k]}')
| column -t
ID Region Strt End Length
sd_2_1 head 1 1 0
sd_2_1 trunk 2 832 830
sd_2_1 tail 833 930 97
sd_3_1 trunk 1 1470 1469
sd_3_1 tail 1471 1649 178
sd_4_1 head 2 50 48
sd_4_1 trunk 51 701 650
Subshell是将标题与正文分开进行处理。将记录分隔符设置为段落模式,找到每条记录的相应长度(因为某些行可能缺失,所以几乎没有复杂性)。选择每个键的最大值并在完成后打印。
如果您需要不同ID行之间的间距。
... | column -t | awk 'NR<3{p=$1} $1!=p{print "";p=$1} 1'
ID Region Strt End Length
sd_2_1 head 1 1 0
sd_2_1 trunk 2 832 830
sd_2_1 tail 833 930 97
sd_3_1 trunk 1 1470 1469
sd_3_1 tail 1471 1649 178
sd_4_1 head 2 50 48
sd_4_1 trunk 51 701 650
答案 1 :(得分:1)
这是perl版本
while(<>) {
chomp;
if ($_ =~ /(head|trunk|tail)/) {
# Parse and store the relevant lines
($id, $region, $start, $end, $length) = split;
$entry{$region} = $_;
if($region eq "trunk") {
$trunklength = $length;
}
} elsif(defined ($id)) {
# Check if this is the greatest trunk length
if($trunklength > $trunklength{$id}) {
# Clear old values
$trunklength{$id}= $trunklength;
undef($trunklength);
# Store new values
$trunk{$id} = $entry{"trunk"};
$head{$id} = $entry{"head"};
$tail{$id} = $entry{"tail"};
}
undef %entry;
}
}
# Print out the answer
foreach $id (sort (keys(%trunklength))) {
print "$head{$id}\n" if (defined($head{$id}));
print "$trunk{$id}\n" if (defined($trunk{$id}));
print "$tail{$id}\n" if (defined($tail{$id}));
print "\n";
}
首先解析头部,开始和尾部线条,将它们存储在由该区域索引的哈希中。存储中继长度。在空行上,将主干长度与id的存储主干长度进行比较。如果它大于先前的head,trunk和length值,则丢弃并替换为当前版本。这适用于缺少某些值的情况。
最后遍历哈希以打印出所需的值。请注意,对于未初始化的变量,perl显而易见,因此不需要检查$trunklength{id}
是否未设置为例。
答案 2 :(得分:0)
应该是awk -F&#34; \ t&#34; &#39; {如果($ ==您最大)}&#39; infile.txt
或者如果你想从以前的管道进程中获取它,我希望你用xargs命令代替max。
你想用grep搜索什么?你还没有给出模式
你的awk没有打印任何东西。我假设这是一次性要求,并且您已经知道最大值,。
您的命令应该类似于
awk '{if($5==max1 || $5==max2 || $5==max3){ print $5 }}' infile.txt | sed 's/ /|/g' | xargs -ipattern grep -C 1 'pattern' >out.txt
- &GT;这里我使用sed转换来自awk的多行输出,并使用xargs将模式传递给grep
- &gt;这里,如果max1,2,3不是整个文件中的唯一数字,则此命令将中断。