![根据字符串过滤文件](https://linux22.com/image/35978/%E6%A0%B9%E6%8D%AE%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%87%E6%BB%A4%E6%96%87%E4%BB%B6.png)
我有一个看起来像这样的文件
a 0 gene1 56 0 6S32M12S *
b 256 gene2 56 0 6S32M12S *
c 256 gene3 55 0 6S27M17S *
d 16 gene4 110 9 19S25M6S *
e 272 gene5 141 9 23S21M6S *
f 272 gene6 139 9 24S20M6S *
g 0 gene7 38 1 6S44M *
h 256 gene8 38 1 6S44M *
I 256 gene9 38 1 6S44M *
j 256 gene10 40 1 8S42M *
第六列是我要过滤的字符串。基本上,如果字符串包含等于或大于 16S(例如 16S、17S、18S、19S 等)的匹配项,则报告这些行。我怎样才能做到这一点?上述示例的输出将是:
c 256 gene3 55 0 6S27M17S *
d 16 gene4 110 9 19S25M6S *
e 272 gene5 141 9 23S21M6S *
f 272 gene6 139 9 24S20M6S *
我刚刚向您展示了一个大文件中的一个小片段。
答案1
perl -ane 'print if grep {$_ >= 16} ($F[5] =~ /(\d+)S/g)' file
输出
c 256 gene3 55 0 6S27M17S *
d 16 gene4 110 9 19S25M6S *
e 272 gene5 141 9 23S21M6S *
f 272 gene6 139 9 24S20M6S *
这会找到第 6 个字段中后跟“S”的所有数字。如果有任何大于或等于 16,则会打印该行。
寻找-n
在perldoc perlrun
查看 perl 对单行代码所做的事情的一种很酷的方法是添加选项-MO=Deparse
$ perl -MO=Deparse -ane 'print if grep {$_ >= 16} ($F[5] =~ /(\d+)S/g)'
LINE: while (defined($_ = <ARGV>)) {
our(@F) = split(' ', $_, 0);
print $_ if grep {$_ >= 16;} $F[5] =~ /(\d+)S/g;
}
-e syntax OK
看
http://perldoc.perl.org/B/Deparse.html
http://perldoc.perl.org/O.html
我将通过将一行展开为脚本来进行解释:
#!/usr/bin/env perl
my $filename = shift @ARGV;
open my $fh, '<', $filename or die $!;
while (defined($_ = <$fh>)) {
my @F = split(' ', $_, 0);
my @s_numbers = $F[5] =~ /(\d+)S/g;
if (grep {$_ >= 16;} @s_numbers) {
print $_;
}
}
close $fh;
答案2
假设第二个S
也很重要:
awk '{
split ($6, nums, /S([0-9]+M)?/);
for (i in nums)
if (nums[i] > 16)
{ print; next }
}' test.txt