verifique se a string está presente em uma lista e produza um terceiro arquivo se a string estiver presente

verifique se a string está presente em uma lista e produza um terceiro arquivo se a string estiver presente

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" fica assim:

abc2
abc10
abc34
abc99
abc78
abc8
abc3
abc5
abc4

Gostaria de pesquisar se cada string em “data.tab” (exceto coluna 1) está presente em “mylist.tab”. Eu gostaria de criar um terceiro arquivo "output.tab" onde, se a string estiver presente, eu incluiria um "1", caso contrário, "0" na respectiva linha/coluna.

Exemplo: "saída.tab"

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

Observe que "data.tab" contém um número diferente de colunas para cada linha.

Responder1

Isso é expresso 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:

analisar.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

Responder2

Perl para o resgate!

Salve os elementos da lista em um hash, leia a tabela, divida em espaços 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";
}

Responder3

Use sedpara criar um sedscript em mylist.tab e executá-lo em data.tab:

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

Observação: presumo que todas as strings em "mylist.tab" tenham pelo menos 2 caracteres.

Responder4

Outra perlsolução

$ 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 }construir um hash de palavras emmylist.tab
  • s/\h\K\H+/$h{$&} ? 1 : 0/gepara linhas em data.tab, substitua por 1if presente na variável hash, senão 0. O \h\Klookbehind é positivo quanto à presença de espaço em branco, evitando assim que a primeira coluna corresponda
  • Em seguida, imprima a linha modificada

informação relacionada