Filtrando um arquivo em uma string

2

Eu tenho um arquivo que se parece com isso

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   *

A sexta coluna é a string que eu quero filtrar. Basicamente, se a string contiver uma correspondência igual ou maior que 16S (então, digamos 16S, 17S, 18S, 19S e mais) do que reportar essas linhas. Como eu posso fazer isso? A saída do exemplo acima seria:

c   256 gene3   55  0   6S27M17S    *
d   16  gene4   110 9   19S25M6S    *
e   272 gene5   141 9   23S21M6S    *
f   272 gene6   139 9   24S20M6S    *

Acabei de mostrar um pequeno trecho de um arquivo grande.

    
por user3138373 06.01.2015 / 19:05

2 respostas

5

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

saídas

c   256 gene3   55  0   6S27M17S    *
d   16  gene4   110 9   19S25M6S    *
e   272 gene5   141 9   23S21M6S    *
f   272 gene6   139 9   24S20M6S    *

Isso encontra todos os dígitos seguidos por "S" no 6º campo. Se algum for maior ou igual a 16, imprime a linha.

Procure -n em perldoc perlrun

Uma forma legal de ver o que o perl está fazendo com um único liner é adicionar a opção -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

veja o link
link

Vou explicar expandindo o one-liner em um script:

#!/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;
    
por 06.01.2015 / 20:24
1

Supondo que o segundo S também seja importante:

awk '{
split ($6, nums, /S([0-9]+M)?/); 
for (i in nums) 
  if (nums[i] > 16) 
    { print; next }
}' test.txt
    
por 06.01.2015 / 19:15