com sed
:
sed '/|/{H;d;};G;s/\([A-Z0-9]*\)\(.*\n\)\(|[^[:cntrl:]]*\)//;P;d' FILE2 FILE1
deve fazer o truque. É uma adaptação de esta resposta . A explicação detalhada está lá.
Eu tenho uma lista grande de dados, como
FILE1 (4600 linhas)
Genome Gene Boolean
E15-12 VFG000923 1
E15-13 VFG000924 1
E15-14 VFG000926 1
E15-15 VFG000928 1
E15-16 VFG000930 1
E15-17 VFG000932 1
E15-18 VFG000933 0
E15-19 VFG001448 0
E15-24 VFG013465 1
Eu quero sub a informação em col2 para se parecer com:
FILE2 (180 linhas)
VFG000923|fepA
VFG000924|fepB
VFG000926|fepD
VFG000928|fepG
VFG000930|entF
VFG000932|entE
VFG000933|entB
VFG001448|kpsD
VFG001450|kpsM
VFG044165|entS
Fora
Genome Gene Boolean
E15-12 VFG000923|fepA 1
E15-13 VFG000924|fepB 1
E15-14 VFG000926|fepD 1
E15-15 VFG000928|fepG 1
E15-16 VFG000930|entF 1
E15-17 VFG000932|entE 1
E15-18 VFG000933|entB 0
E15-19 VFG001448|kpsD 0
E15-20 VFG001450|kpsM 1
Usando código por @ val0x00ff (veja os comentários)
Genome Gene Boolean
E15-14 VFG000923|fepA 1
E15-14 VFG000924|fepB 0
E15-14 VFG000926|fepD 1
E15-14 VFG000928|fepG 0
Existe uma maneira de fazer isso com sed ou awk?
com sed
:
sed '/|/{H;d;};G;s/\([A-Z0-9]*\)\(.*\n\)\(|[^[:cntrl:]]*\)//;P;d' FILE2 FILE1
deve fazer o truque. É uma adaptação de esta resposta . A explicação detalhada está lá.
Isso deve funcionar:
$ awk 'NR==FNR{k=sub(/\|.*/,$1); a[k]=$1; next} ($2 in a){$2=a[$2]}1' file2 file
Genome Gene Boolean
E15_14 VFG000923|fepA 1
E15_14 VFG000924|fepB 1
E15_14 VFG000926|fepD 0
E15_14 VFG000928|fepG 1
E15_14 VFG000930|entF 0
E15_14 VFG000932|entE 0
E15_14 VFG000933|entB 1
E15_14 VFG001448|kpsD 1
E15_14 VFG001450|kpsM 1
E15_14 VFG044165|entS 0
Ou, um pouco mais fácil de ler:
awk 'NR==FNR{
k=sub(/\|.*/,$1);
a[k]=$1;
next
}
($2 in a){
$2=a[$2]
}1' file2 file
NR==FNR{ }
: NR é o número da linha de entrada atual e FNR é o número da linha do arquivo atual. Ao ler mais de um arquivo, os dois serão iguais apenas durante a leitura do primeiro arquivo. k=sub(/\|.*/,$1);
: remova a parte depois do |
da linha (isto só acontece para o primeiro arquivo por causa do NR==FNR
como explicado acima). a[k]=$1;
: salve o primeiro campo do primeiro arquivo como um valor na matriz a
cuja chave é o nome do gene (o primeiro campo com tudo após o |
removido). next
: pule para a próxima linha. Isso garante que não executemos o próximo bloco durante a leitura do primeiro arquivo. ($2 in a)
: se o segundo campo existir como uma chave na matriz a
(isso só será executado para o segundo arquivo). $2=a[$2]
: defina o segundo campo para o que foi armazenado em a
para $2
. 1
: esta é uma abreviação de awk para "imprimir a linha atual". funciona porque a ação padrão quando algo é avaliado como verdadeiro no awk é imprimir a linha atual. Como 1
é sempre verdadeiro, isso será impresso. perl -lne '
@ARGV and %h=(%h, /(.*)\|/ => $_),next;
!@ARGV and !$a++ and print,next;
print s//$h{$1}/r if exists $h{(/\h\K(\S+)(?=\h)/)[0]};
' FILE2 FILE1
%h
que é keyed
nos dados antes de |
e o valor é toda a linha. !@ARGV and !$a++
que significa @ARGV
foi esvaziado e estamos vendo a variável $a
pela primeira vez. regex
/\h\S+\h/
para ver se essa chave existe no hash %h
. Quando isso for verdade, substituiremos esse campo pelo valor correspondente a essa chave. Tags text-processing awk sed