根据字符串过滤文件

use*_*373 2 shell awk text-processing

我有一个看起来像这样的文件

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   *
Run Code Online (Sandbox Code Playgroud)

第 6 列是我要过滤的字符串。基本上,如果字符串包含等于或大于 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    *
Run Code Online (Sandbox Code Playgroud)

我刚刚向您展示了一个大文件中的一个小片段。

gle*_*man 5

perl -ane 'print if grep {$_ >= 16} ($F[5] =~ /(\d+)S/g)' file
Run Code Online (Sandbox Code Playgroud)

产出

c   256 gene3   55  0   6S27M17S    *
d   16  gene4   110 9   19S25M6S    *
e   272 gene5   141 9   23S21M6S    *
f   272 gene6   139 9   24S20M6S    *
Run Code Online (Sandbox Code Playgroud)

这会在第 6 个字段中找到所有后跟“S”的数字。如果任何大于或等于 16,则打印该行。


寻找-nperldoc 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
Run Code Online (Sandbox Code Playgroud)


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;
Run Code Online (Sandbox Code Playgroud)