![verifique se a string está presente em uma lista e produza um terceiro arquivo se a string estiver presente](https://rvso.com/image/97245/verifique%20se%20a%20string%20est%C3%A1%20presente%20em%20uma%20lista%20e%20produza%20um%20terceiro%20arquivo%20se%20a%20string%20estiver%20presente.png)
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 sed
para criar um sed
script 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 perl
soluçã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/ge
para linhas emdata.tab
, substitua por1
if presente na variável hash, senão0
. O\h\K
lookbehind é positivo quanto à presença de espaço em branco, evitando assim que a primeira coluna corresponda- Em seguida, imprima a linha modificada