verificar se a string está presente em uma lista e gerar um terceiro arquivo se a string estiver presente

1

Eu tenho 2 arquivos ("data.tab" e "mylist.tab").

meu arquivo "data.tab" se parece com:

Info_1    abc1     abc2     abc3
Info_2    abc5     ghi4
Info_3    abc10
Info_4    abc8     abc7     abc87    klm78    abc99
Info_5    

meu arquivo "mylist.tab" é assim:

abc2
abc10
abc34
abc99
abc78
abc8
abc3
abc5
abc4

Eu gostaria de pesquisar se cada string em "data.tab" (exceto a coluna 1) está presente em "mylist.tab". Eu gostaria de criar um terceiro arquivo "output.tab", onde se a cadeia estiver presente, então eu incluiria um "1", senão "0" na respectiva linha / coluna.

Exemplo: "output.tab"

Info_1   0    1     1
Info_2   1    0
Info_3   1
Info_4   1    0     0    0    1
Info_5   

Por favor, note que "data.tab" contém diferentes números de colunas para cada linha.

    
por biobudhan 25.10.2016 / 14:23

4 respostas

2

Perl para o resgate!

Salve os elementos da lista em um hash e, em seguida, leia a tabela, divida no espaço em branco e verifique o hash para imprimir 0 ou 1.

#!/usr/bin/perl
use warnings;
use strict;

my %in_list;
open my $LIST, '<', 'mylist.tab' or die $!;
while (<$LIST>) {
    chomp;
    $in_list{$_} = 1;
}

open my $TAB, '<', 'data.tab';
while (<$TAB>) {
    my @cells = split;
    print shift @cells, "\t";
    print join "\t", map $in_list{$_} ? 1 : 0, @cells;
    print "\n";
}
    
por 25.10.2016 / 14:38
3

Isso é expressado diretamente no awk:

awk 'FNR==NR { h[$1]; next } { for(i=2; i<=NF; i++) $i = ($i in h)? 1 : 0 } 1' mylist.tab data.tab

Ou em um formato mais legível:

parse.awk

# Collect mylist.tab into the 'h' associative array
FNR==NR {
  h[$1]
  next
}

# For all but the first column in data.tab check and record if it is in 'h'
{ 
  for(i=2; i<=NF; i++) 
    $i = ($i in h) ? 1 : 0 
}

# Short for { print $0 }
1

Execute assim:

awk -f parse.awk mylist.tab data.tab

Saída:

Info_1 0 1 1
Info_2 1 0
Info_3 1
Info_4 1 0 0 0 1
Info_5

Ou para colunas delimitadas por tabulações:

awk -v OFS='\t' -f parse.awk mylist.tab data.tab

Saída:

Info_1  0   1   1
Info_2  1   0
Info_3  1
Info_4  1   0   0   0   1
Info_5
    
por 25.10.2016 / 14:59
2

Use sed para criar um script sed em mylist.tab e executá-lo em data.tab:

sed \
    -e '1i s/^[ \t]*//' \
    -e 's@\(.*\)@s/\([ \t]\)\b/\11/@g' \
    -e '$as/\([ \t]\)[^ \t]\{2,\}\b/\10/g' mylist.tab \
    > /tmp/x.sed 
sed -f /tmp/x.sed data.tab

Note que todas as strings em "mylist.tab" têm pelo menos 2 caracteres.

    
por 25.10.2016 / 15:05
1

Outra perl solution

$ perl -lne 'if(!$#ARGV){ $h{$_}=1 }
             else{ s/\h\K\H+/$h{$&} ? 1 : 0/ge; print }
            ' mylist.tab data.tab
Info_1    0     1     1
Info_2    1     0
Info_3    1
Info_4    1     0     0    0    1
Info_5    
  • if(!$#ARGV){ $h{$_}=1 } cria um hash de palavras em mylist.tab
  • s/\h\K\H+/$h{$&} ? 1 : 0/ge para linhas em data.tab , substitua por 1 se presente na variável hash, senão 0 . O \h\K é lookbehind positivo para presença de espaço em branco, evitando assim que a primeira coluna corresponda
  • Em seguida, imprima a linha modificada
por 25.10.2016 / 16:13