Combinando dois arquivos e mantendo blocos que contêm a correspondência

1

Eu tenho dois arquivos e estou tentando combiná-los e manter blocos inteiros de file1 ( matched e unmatched elements), mas para alterar nomes de arquivos dos elementos que estão correspondendo.

File1 :

3L21_NAJOX  Naja oxiana P01382  PDB; 1NTN; X-ray; 1.90 A; A=1-73.
                                PDB; 1W6B; NMR; -; A=1-73.

3LKB_BUNMU  Bungarus multicinctus   P01398  PDB; 1KBA; X-ray; 2.30 A; A/B=22-87.
                                            PDB; 2NBT; NMR; -; A/B=22-87.

3NOJ_BUNCA  Bungarus candidus   P81782  PDB; 1F94; X-ray; 0.97 A; A=1-63.
                                        PDB; 1IJC; NMR; -; A=1-63. 

A coluna que está logo após PDB; é o que eu estou combinando.

O file2 é uma lista de nomes (as primeiras quatro letras são importantes):

1KBA_GAL.pdb
1A3L_CFC.pdb
1F94_.pdb
1A3U_.pdb
1A3V_.pdb
1A4H_.pdb

Portanto, estou tentando corresponder nomes (as primeiras quatro letras) do segundo arquivo com os nomes que aparecem logo após a coluna PDB; no primeiro arquivo. Se o nome no elemento do file1 corresponder a um no segundo arquivo, mantenha o bloco inteiro ( matched e unmatched elements), mas substitua os nomes dos elementos no file1 , com o nome elementos do file2

Assim, neste exemplo, a saída que desejo é:

3LKB_BUNMU  Bungarus multicinctus   P01398  PDB; 1KBA_GAL; X-ray; 2.30 A; A/B=22-87.
                                            PDB; 2NBT; NMR; -; A/B=22-87

3NOJ_BUNCA  Bungarus candidus   P81782  PDB; 1F94_; X-ray; 0.97 A; A=1-63.
                                        PDB; 1IJC; NMR; -; A=1-63. 

Alguém tem uma ideia de como fazer isso?

    
por sergio 27.02.2018 / 08:33

2 respostas

1

Ok, vamos experimentar este pequeno roteiro que eu criei:

#!/usr/bin/env bash
set -e

match1=/home/george/Documents/askubuntu/matchme/match1
match2=/home/george/Documents/askubuntu/matchme/match2

# Create the result file
touch results.txt

while read -r word
do
     if [[ "$word" = $(grep -o "$word" "$match1") ]]; then
             if [[ "$word" != $(grep -o "$word" "results.txt") ]]
             then
                     grep "$(grep "$word" "$match1" | grep -o "[[:digit:]]..$")" "$match1" >> "results.txt"
                     while read -r new
                     do                                 
                             if [[ "$new" =~ $word ]]; then
                                     # Replace the words
                                     sed -i "s/$word/$new/" "results.txt"
                             fi
                     done < <(grep  -o "$word_.*\." "$match2" | sed -e 's/\.//')
                     # Add space between results
                     echo " " >> "results.txt"
             fi
     fi
done < <(cut -d"_" -f1 "$match2")

# Remove last blank line from the results file
sed -i '$ d' results.txt

Explicação:

  • match1 : contém a fonte do filtro
  • match2 : contém os critérios de filtro
  • set -e : script de parada ocorre erro
  • (grep -o "$word_.*\." "$match2" | sed -e 's/\.//') : leia o arquivo de filtro e pegue os nomes até a extensão pdb

Descrição do processo de comando:

  1. Usando o comando cut , obtenha os critérios de filtro do arquivo match2 (1KBA, 1A3L, 1F94, 1A3U, 1A3V, 1A4H) e, em seguida,
  2. Leia o resultado do comando cut e encontre correspondências no arquivo de fontes match1 ,
  3. Se uma correspondência for encontrada grep para esse bloco no arquivo de origem e enviar ou imprimir para um novo arquivo result.txt

NOTA: Por favor modifique nomes e outros parâmetros ao seu gosto.

RESULTADOS:

$cat results.txt 
3LKB_BUNMU  Bungarus multicinctus   P01398  PDB; 1KBA_GAL; X-ray; 2.30 A; A/B=22-87.
                                        PDB; 2NBT; NMR; -; A/B=22-87.

3NOJ_BUNCA  Bungarus candidus   P81782  PDB; 1F94_; X-ray; 0.97 A; A=1-63.
                                    PDB; 1IJC; NMR; -; A=1-63. 
    
por George Udosen 27.02.2018 / 10:14
1

Sugiro usar awk no modo de parágrafo , por exemplo

awk 'NR==FNR {
       sub(/_[^_]*$/,"",$1); a[$1]++; next
     } 
     {
       for (x in a) {
         if ($0 ~ "PDB; "x) {print; break;}
       }
     }' file2 RS= file1

Ex .:

$ awk 'NR==FNR {sub(/_[^_]*$/,"",$1); a[$1]++; next} {for (x in a) {if ($0 ~ "PDB; "x) {print; break;}}}' file2 RS= file1
3LKB_BUNMU  Bungarus multicinctus   P01398  PDB; 1KBA; X-ray; 2.30 A; A/B=22-87.
                                            PDB; 2NBT; NMR; -; A/B=22-87.
3NOJ_BUNCA  Bungarus candidus   P81782  PDB; 1F94; X-ray; 0.97 A; A=1-63.
                                        PDB; 1IJC; NMR; -; A=1-63. 

Se você quiser uma linha em branco após cada bloco, poderá alterar {print; break;} para {print $0"\n"; break;} ou {printf "%s\n\n", $0; break} , mas observe que isso adicionará uma linha em branco após o último registro em que talvez não tenha sido originalmente. se você tiver o GNU awk ( gawk ), você pode evitar isso acessando a variável especial RT que contém o separador real para cada registro, isto é, {printf "%s%s", $0, RT; break;}

    
por steeldriver 27.02.2018 / 14:48