Perl 计算文本文件中匹配术语的数量?
我试图从一个输入列表中计算匹配项的数量,该列表包含数据文件中每行一个项,并创建一个输出文件,其中包含匹配(grep'd)项和匹配项的数量 input_list.txt如下所示:Perl 计算文本文件中匹配术语的数量?,perl,unix,grep,match,Perl,Unix,Grep,Match,我试图从一个输入列表中计算匹配项的数量,该列表包含数据文件中每行一个项,并创建一个输出文件,其中包含匹配(grep'd)项和匹配项的数量 input_list.txt如下所示: + 5S_rRNA + 7SK + AADAC + AC000111.3 + AC000111.6 data.txt文件: chr10 101780038 101780209 5S_rRNA chr10 103578280 103578430 5S_rRNA chr10 112327234
+ 5S_rRNA
+ 7SK
+ AADAC
+ AC000111.3
+ AC000111.6
data.txt文件:
chr10 101780038 101780209 5S_rRNA
chr10 103578280 103578430 5S_rRNA
chr10 112327234 112327297 5S_rRNA
chr10 120766459 120766601 7SK
chr10 127408228 127408317 7SK
chr10 127511874 127512063 AADAC
chr10 14614140 14614294 AC000111.3
chr10 14695964 14696146 AC000111.6
我想创建一个输出文件(output.txt),其中包含匹配的术语及其相应的计数
+ 5S_rRNA 3
+ 7SK 2
+ AADAC 1
+ AC000111.3 1
+ AC000111.6 1
到目前为止,我已经使用下面的脚本生成了一个包含所有匹配项的列表,但是所有提供匹配项计数的尝试都没有成功
exec < input_list.txt
while read line
do
grep -w data.txt | awk '{print $0}'| sort| uniq >> grep_output.txt
done
exec>grep|u output.txt
完成
我尝试了grep-o-w | wc-l和grep-w data.txt | wc-l
等,但我无法确定如何生成包含匹配项及其相应计数的输出列表
任何建议都很好 您可以将input.txt中的单词变灰,并使用uniq获取计数:
cut -d' ' -f2 input.txt | grep -o -f - data.txt | sort | uniq -c
给出:
您还可以添加另一个sed以获得格式化输出:
cut -d' ' -f2 input.txt | grep -o -f - data.txt | sort | uniq -c | \
sed 's/\s*\([0-9]*\)\s*\(.*\)/+ \2\t\1/'
产生:
awk
可以很好地实现这一点:
$ awk 'NR==FNR {vals[$2]=$2}
$4 in vals {count[$4]++}
END {for (i in count) print i, count[i]}' input_list data.txt
AC000111.3 1
AC000111.6 1
5S_rRNA 3
AADAC 1
7SK 2
解释
vals[]
存储输入列表
文件的第二个字段。然后,它检查第二个文件data.txt
的第四个字段是否在任何行中,并统计count[]
数组中的出现次数。最后,它在END{}
块中打印输出
通过n
(数字)r
(反向)和k2
(第二列)选项,您可以获得排序数据:
$ awk 'NR==FNR {vals[$2]=$2}
$4 in vals {count[$4]++}
END {for (i in count) print i, count[i]}' input_list data.txt | sort -rnk2
5S_rRNA 3
7SK 2
AC000111.6 1
AC000111.3 1
AADAC 1
你可以这样做——这可能就是你自己的目标。它基本上使用“wc-l”统计匹配数,如果大于零,则输出搜索字符串和匹配数:
#!/bin/bash
while read line
do
line=${line##+ } # Strip off leading + and space
n=$(grep "$line" data.txt 2> /dev/null | wc -l)
if [ $n -gt 0 ]; then
echo $line $n
fi
done < input_list.txt
#/bin/bash
读行时
做
line=${line###+}#去掉前导+和空格
n=$(grep“$line”data.txt 2>/dev/null | wc-l)
如果[$n-gt 0];然后
echo$line$n
fi
完成
您也可以在perl中使用哈希来实现这一点:
#!/usr/bin/perl
use warnings;
use strict;
open my $list, '<', 'in.txt' or die "$!";
open my $input, '<', 'in.2.txt' or die "$!";
my @split;
my (%data, %hash, %exists);
while(<$input>){
chomp;
@split = split(/\s+/);
my ($info) = $split[3];
$data{$info}++;
}
while (<$list>){
chomp;
my @split = split(/\+ /);
my ($match) = $split[1];
$hash{$match} = 1;
}
my $count = 0;
for my $compare (keys %hash){
if (exists $data{$compare} ){
$exists{$compare} = $data{$compare};
}
}
foreach my $c (keys %exists){
print "+ $c: $exists{$c}\n"
}
+1.然而,对于所需的格式,我宁愿使用
paste
。类似于:paste-d''input.txt此外,sort
管道在这里可能没有用。愚蠢的问题是,如何将输出打印到单独的文件中?谢谢两个回音。。。“echo$line”然后在下一行“echo$n”仍在打印到屏幕上将“>yourOutputFile”添加到最后一行的末尾。
#!/bin/bash
while read line
do
line=${line##+ } # Strip off leading + and space
n=$(grep "$line" data.txt 2> /dev/null | wc -l)
if [ $n -gt 0 ]; then
echo $line $n
fi
done < input_list.txt
perl -lane '$s{ $F[3] }++ END{ print "+ $_ $s{$_}" for sort keys %s }' data.txt
#!/usr/bin/perl
use warnings;
use strict;
open my $list, '<', 'in.txt' or die "$!";
open my $input, '<', 'in.2.txt' or die "$!";
my @split;
my (%data, %hash, %exists);
while(<$input>){
chomp;
@split = split(/\s+/);
my ($info) = $split[3];
$data{$info}++;
}
while (<$list>){
chomp;
my @split = split(/\+ /);
my ($match) = $split[1];
$hash{$match} = 1;
}
my $count = 0;
for my $compare (keys %hash){
if (exists $data{$compare} ){
$exists{$compare} = $data{$compare};
}
}
foreach my $c (keys %exists){
print "+ $c: $exists{$c}\n"
}
+ 5S_rRNA: 3
+ AADAC: 1
+ 7SK: 2
+ AC000111.6: 1
+ AC000111.3: 1