Соответствие двум файлам и хранение блоков, которые содержат соответствие

У меня есть два файла, и я пытаюсь соответствовать им и сохранить целые блоки от file1 (matched и unmatched элементы), но изменить имена файлов элементов, которые подбираются.

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. 

Столбец, который является сразу после PDB; то, чему я соответствую.

file2 список имен (первые четыре буквы важны):

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

Таким образом, я пытаюсь соответствовать именам (первые четыре буквы) из второго файла с именами, которые появляются сразу после PDB; столбец в первом файле. Если имя в элементе от file1 соответствия один во втором файле, затем сохраните целый блок (также matched и unmatched элементы), но замена названия элементов в file1, с элементами от file2

Таким образом от этого примера, вывод, который я хочу:

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. 

У кого-либо есть идея, как сделать это?

1
задан 2 March 2018 в 08:04

2 ответа

Хорошо позволяет, пробуют этот небольшой сценарий, который я вызвал в воображении:

#!/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

Объяснение:

  • match1: содержит источник фильтра
  • match2: содержит критерии фильтра
  • set -e: остановитесь сценарий является ошибкой, происходит
  • (grep -o "$word_.*\." "$match2" | sed -e 's/\.//'): считайте файл фильтра и захватите имена до pdb расширение

Описание процесса команды:

  1. Используя cut команда получает критерии фильтра из файла match2 (1KBA, 1A3L, 1F94, 1A3U, 1A3 В, 1A4H), затем
  2. Читайте из cut управляйте заканчиваются и находят соответствия в исходном файле match1,
  3. Если соответствие найдено grep для того блока в исходном файле и отправляют или печатают в новый файл result.txt

Примечание: Измените имена и другие параметры к Вашему вкусу.

РЕЗУЛЬТАТЫ: 

$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. 
1
ответ дан 7 December 2019 в 13:26

Я предложил бы использовать awk в режиме абзаца, например.

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

Напр.:

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

Если Вы хотите пустую строку после каждого блока, можно измениться {print; break;}кому: {print $0"\n"; break;} или {printf "%s\n\n", $0; break} хотя примечание, что это добавит строку конечного пробела после последней записи, где не могло быть того первоначально - если у Вас есть GNU awk (gawk) можно избежать этого путем доступа к специальной переменной RT который содержит фактический разделитель для каждой записи т.е. {printf "%s%s", $0, RT; break;}

1
ответ дан 7 December 2019 в 13:26

Другие вопросы по тегам:

Похожие вопросы: