У меня есть два файла, и я пытаюсь соответствовать им и сохранить целые блоки от 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.
У кого-либо есть идея, как сделать это?
Хорошо позволяет, пробуют этот небольшой сценарий, который я вызвал в воображении:
#!/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
расширениеОписание процесса команды:
cut
команда получает критерии фильтра из файла match2
(1KBA, 1A3L, 1F94, 1A3U, 1A3 В, 1A4H), затемcut
управляйте заканчиваются и находят соответствия в исходном файле match1
,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.
Я предложил бы использовать 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;}