Как я могу сравнить 3 файла вместе (чтобы увидеть, что общего между ними)?

#linux #comparison #awk #wc

#linux #сравнение #awk #wc

Вопрос:

Я хочу сравнить 3 файла вместе, чтобы увидеть, какая часть информации в файлах одинакова. Формат файла примерно такой:

 Chr11   447     .       A       C       74      .       DP=22;AF1=1;CI95=1,1;DP4=0,0,9,8;MQ=15;FQ=-78   GT:PL:GQ        1/1:107,51,0:99
Chr10   449     .       G       C       35      .       DP=26;AF1=0.5;CI95=0.5,0.5;DP4=5,0,7,8;MQ=20;FQ=11.3;PV4=0.055,0.0083,0.028,1   GT:PL:GQ        0/1:65,0,38:41
Chr12   517     .       G       A       222     .       DP=122;AF1=1;CI95=1,1;DP4=0,0,77,40;MQ=23;FQ=-282       GT:PL:GQ        1/1:255,255,0:99
Chr10   761     .       G       A       41      .       DP=93;AF1=0.5;CI95=0.5,0.5;DP4=11,34,6,35;MQ=19;FQ=44;PV4=0.29,1.8e-35,1,1      GT:PL:GQ        0/1:71,0,116:74
 

Меня интересуют только первые два столбца (если первые два столбца совпадают, то я считаю их равными). Это команда, которую я использую для сравнения двух файлов :

 awk 'FILENAME==ARGV[1] {pair[$1 " " $2]; next} ($1 " " $2 in pair)'  file1 file2 | wc -l
 

Я хотел бы использовать команду awk, так как мои файлы действительно большие, и awk обрабатывает их действительно хорошо! но я не мог понять, как использовать его для 3 файлов!

Комментарии:

1. Как бы вы хотели представить общие строки? Распечатайте их все? или просто распечатать первые 2 столбца?

2. все было бы намного лучше!

3. итак, для записи, в которой первые 2 столбца одинаковы, но другие столбцы отличаются в каждом файле, вы хотите, чтобы были напечатаны все 3 строки?

4. кроме того, для каждого файла можно с уверенностью предположить, что пара column1-column2 уникальна?

5. дело в том, что мне это нужно для двух целей, сначала я хочу знать, сколько из них похоже! так что не имеет значения, будут ли использоваться только первые два столбца! но для второй цели я хотел бы иметь всю информацию, если это возможно, в одной строке (все три строки будут напечатаны в одной строке или что-то в этом роде), чего я не хочу, так это иметь 3 строки для одной позиции!

Ответ №1:

Не предназначено для начала войны редакторов, но я знаком с VI, а vimdiff и его варианты показывают сравнение между несколькими файлами в параллельном представлении, что я нахожу очень удобным. Просто вы можете вызвать его с помощью

 $ vimdiff <filelist>
 

Ответ №2:

Если просто распечатать пары (column1 column2), которые являются общими для всех 3 файлов, и использовать тот факт, что пара уникальна в файле, вы могли бы сделать это таким образом:

 awk '{print $1" "$2}' a b c | sort | uniq -c | awk '{if ($1==3){print $2" "$3}}'
 

Это можно сделать с произвольным количеством файлов, если вы измените параметр последней команды.

Вот что он делает:

  1. печатает и сортирует первые 2 столбца всех файлов ( awk '{print $1" "$2}' a b c | sort )
  2. подсчитайте количество повторяющихся записей ( uniq -c )
  3. если количество повторяющихся записей == количество файлов, мы нашли совпадение. распечатайте его.

Если вы делаете это часто, вы можете выразить это как функцию bash (и добавить ее в свой .bashrc ), которая параметризует количество файлов.

 function common_pairs { 
    awk '{print $1" "$2}' $@ | sort | uniq -c | awk -v numf=$# '{if ($1==numf){print $2" "$3}}'; 
}
 

Вызовите его с любым количеством файлов, которые вы хотите: common_pairs file1 file2 file3 fileN

Ответ №3:

Для этого я бы использовал команды cut, sort и comm .

  1. С помощью cut срежьте ненужные поля.
  2. отсортируйте результат, поскольку comm ожидает отсортированных входных данных.
  3. Используйте comm, чтобы получить строки, которые находятся в file1 и file2.
  4. Снова используйте comm, чтобы получить строки, которые также находятся в file3.

Сценарий может выглядеть следующим образом:

  for i in 1 2 3
  do
   # options to cut may have to be adjusted for your input files
   cut -c1-15 file$i | sort > tmp.$i
  done

 comm -12 tmp.1 tmp.2   > tmp.1 2
 comm -12 tmp.3 tmp.1 2 > tmp.1 2 3
 

(Конечно, можно использовать расширенный синтаксис оболочки, чтобы избежать временных файлов, но я не хочу скрывать идею, стоящую за сложными синтаксическими выражениями)

Теперь в файле tmp.1 2 3 у вас должны быть ключи, присутствующие во всех трех файлах. Если вас интересуют целые строки, вы можете использовать команду join в сочетании с отсортированной версией любого из трех входных файлов)

Комментарии:

1. Это также может быть выражено как comm -12 <(awk '{print $1" "$2}' a|sort) <(awk '{print $1" "$2}' b|sort) | comm -12 - <(awk '{print $1" "$2}' c|sort)

2. Да, но утомительно разбирать для новичка — вот почему я не использовал этот синтаксис

Ответ №4:

Просто прочитайте ваш последний комментарий — вы хотите, чтобы файлы были объединены, но дубликаты удалены?

  sort file1 file2 file3 | uniq > newfile
 

Комментарии:

1. Или просто sort -u file1 file2 file3 , но я считаю, что это не то, о чем просит OP.