Замена соответствующих записей в одном столбце файла другим столбцом из другого файла

8

У меня есть два файла, разделенных табуляцией, которые выглядят следующим образом:

file1:

NC_008146.1     WP_011558474.1  1155234 1156286 44173
NC_008146.1     WP_011558475.1  1156298 1156807 12
NC_008146.1     WP_011558476.1  1156804 1157820 -3
NC_008705.1     WP_011558474.1  1159543 1160595 42748
NC_008705.1     WP_011558475.1  1160607 1161116 12
NC_008705.1     WP_011558476.1  1161113 1162129 -3
NC_009077.1     WP_011559727.1  2481079 2481633 8
NC_009077.1     WP_011854835.1  1163068 1164120 42559
NC_009077.1     WP_011854836.1  1164127 1164636 7

file2:

NC_008146.1     GCF_000014165.1_ASM1416v1_protein.faa
NC_008705.1     GCF_000015405.1_ASM1540v1_protein.faa
NC_009077.1     GCF_000016005.1_ASM1600v1_protein.faa

Я хочу сопоставить столбец 1 файла1 с файлом2 и заменить себя соответствующей записью столбца 2 файла 2. Вывод будет выглядеть следующим образом:

GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7
BhushanDhamale
источник
Похоже, вас также может заинтересовать наш родственный сайт: Биоинформатика .
Terdon
Спасибо за ссылку @terdon!
BhushanDhamale

Ответы:

14

Вы можете сделать это очень легко с awk:

$ awk 'NR==FNR{a[$1]=$2; next}{$1=a[$1]; print}' file2 file1
GCF_000014165.1_ASM1416v1_protein.faa WP_011558474.1 1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa WP_011558475.1 1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa WP_011558476.1 1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa WP_011558474.1 1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa WP_011558475.1 1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa WP_011558476.1 1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa WP_011559727.1 2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa WP_011854835.1 1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa WP_011854836.1 1164127 1164636 7

Или, так как это выглядит как разделенный табуляцией файл:

$ awk -vOFS="\t" 'NR==FNR{a[$1]=$2; next}{$1=a[$1]; print}' file2 file1
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa   WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa   WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa   WP_011854836.1  1164127 1164636 7

Это предполагает, что каждый NC_*идентификатор RefSeq ( ) в file1имеет соответствующую запись в file2.

объяснение

  • NR==FNR: NR - номер текущей строки, FNR - номер строки текущего файла. Они будут идентичны только во file2время чтения 1-го файла (здесь ).
  • a[$1]=$2; next: если это первый файл (см. выше), сохраните 2-е поле в массиве, ключом которого является 1-е поле. Затем перейдите к nextлинии. Это гарантирует, что следующий блок не будет выполнен для 1-го файла.
  • {$1=a[$1]; print}: теперь, во втором файле, установите для 1-го поля значение, которое было сохранено в массиве aдля 1-го поля (то есть, связанное значение из file2), и выведите полученную строку.
Тердон
источник
1
NR == FNRне работает правильно, когда первый файл пуст. См. Этот и связанный ответ для обходного пути
iruvar
3
@iruvar Ничто не будет работать хорошо, если первый файл пуст, поэтому я не понимаю, почему это важно. Весь смысл в том, чтобы объединить данные из двух файлов. Если какой-либо файл пуст, все упражнение бессмысленно.
Тердон
извините я должен был сказать в данном конкретном случае file2и не file1пусто. Разумное поведение, когда file2пусто, чтобы сообщить о содержимом file1. Проблема в NR == FNRтом, что связанный с ним код выполняется на содержимом file1file2
аргумента
3
@iruvar здесь нет нормального поведения, если любой файл пуст. Вот что я говорю :) Так что пытаться изящно разобраться с этим делом бессмысленно. И, в любом случае, когда любой файл здесь пуст, ничего не печатается. Что на самом деле кажется самым разумным подходом, я предпочел бы получить не данные, а неверные данные.
Terdon
17

Нет необходимости в awk, если файлы отсортированы, вы можете использовать coreutils join:

join -o '2.2 1.2 1.3 1.4 1.5' file1 file2

Вывод:

GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7

Если ваши файлы не отсортированы, вы можете либо отсортировать их сначала ( sort file1 > file1.sorted; sort file2 > file2.sorted), а затем использовать приведенную выше команду, либо, если ваша оболочка поддерживает <()конструкцию (bash делает), вы можете сделать:

join -o '2.2 1.2 1.3 1.4 1.5' <(sort file1) <(sort file2)
Тор
источник
0

Протестировано с приведенной ниже командой и работает нормально

for i in `awk '{print $1}' f2`; do k=`awk -v i="$i" '$1==i {print $2}' f2`;sed  "/$i/s/$i/$k/g" f1 >f3;done

вывод

for i in `awk '{print $1}' f2`; do k=`awk -v i="$i" '$1==i {print $2}' f2`;sed  "/$i/s/$i/$k/g" f1 >f3;done


GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7
Правин Кумар Б.С.
источник