Substituir texto por valores

1

Eu tenho dois arquivos que precisam ser mesclados em um.

Exemplo do arquivo 1:

gene_1  578
gene_2  565
gene_3  3
gene_4  77
gene_5  8
gene_6  0
gene_7  45
gene_8  67
gene_9  0
gene_10 65

Exemplo de arquivo2:

COG0430 gene_5 gene_9       
COG1949 gene_1 gene_3 gene_6
COG5049 gene_2 gene_4 gene_7 gene_10
COG5104 gene_8

O arquivo de saída deve ficar assim:

COG0430 8 0 
COG1949 578 3 0
COG5049 565 77 45 65
COG5104 67

Alguém sabe um comando que pode resolver este problema?

    
por Kamila 06.07.2018 / 15:30

4 respostas

0
#!/bin/bash
declare -A arr
readarray -t lines < "file1"

for line in "${lines[@]}"; do
   arr[${line%% *}]=${line#* }
done

readarray -t lines2 < "file2"

for line in "${lines2[@]}"; do
    echo -n "${line%% *} "
    for word in $line; do
        echo -n "${arr[$word]} "
    done
    echo
done

Não é o mais limpo, mas funciona. Também verifique se você tem bash > = 4.2

    
por 06.07.2018 / 15:53
0

Aqui está uma maneira

awk '/^gene/{a[$1]=$2}/^COG/{c=$1;for(b=1;b<=NF;b++){c=sprintf("%s%s%c",c,a[$b],b==NF?"":" ")}print c}' file1 file2
COG0430 8 0
COG1949 578 3 0
COG5049 565 77 45 65
COG5104 67
  • /gene/{a[$1]=$2} procura por linhas com "gene" no início e cria uma matriz com um item, com uma chave da primeira coluna (por exemplo, "gene_1") e um valor da próxima coluna (por exemplo, "578")
  • /^COG/ procura por linhas com "COG" no início ...
  • c=$1 define a variável c para a primeira coluna, e. "COG0430"
  • {c=sprintf("%s%s%c",c,a[$b],b==NF?"":" " continua anexando a entrada da matriz para cada coluna na variável c. Se não for a última coluna, coloque um delimitador de espaço.
  • print c , em seguida, apenas imprime a variável totalmente formada "c"
por 06.07.2018 / 15:52
0

Você pode tentar este awk

awk '
  NR == FNR {
    a[$1] = $2
    next
  }
  {
    for ( i = 2 ; i <= NF ; i++)
    $i = a[$i]
  }
1' file1 file2

ou em uma linha

awk 'NR==FNR{a[$1]=$2;next}{for(i=2;i<=NF;i++)$i=a[$i]}1' file1 file2
    
por 06.07.2018 / 18:50
0
 perl -ale '
    $h{$F[0]}=$F[1],next if @ARGV;
    my $k;
    print s/\H+/$k++ ? $h{$&} : $&/reg;
 ' file1 file2

° Lendo o primeiro arquivo, @ARGV contém o segundo argumento e, portanto, retorna verdadeiro.

° Preencher um hash %h com chaves como nomes de genes e os valores correspondentes do segundo campo, para cada linha de arquivo1.

° para o segundo arquivo, @ARGV não conterá nada e, portanto, retornará um falso. As duas últimas linhas de código serão executadas para cada linha de arquivo2.

° Inicialize a variável de contagem toda vez que uma linha de arquivo2 for lida. Em seguida, o \H+ deve corresponder a uma execução de caracteres não horizontais em branco, ou seja, um campo. E no dia 2 em diante, os subs do nome do gene = > o número do gene é acionado.

O editor sed com extensões do Gnu também pode fazer isso:

 sed -Ee '
     # store file1 in hold
    /^C/!{H;1h;d;}

    # place a traveling marker \n\n at $2
    s/$/ /
    G
    s/(\S+\s+)/&\n\n/

    # effect gene name => gene number 
    :a
       s/\n\n(\S+)[ ]+((.*\n)?\s+([0-9]+))/ \n\n/
    ta

   # take away marker and hold portion
    s/\n\n.*//
 ' file1 file2 
    
por 08.07.2018 / 09:57