Я хотел бы объединить два файла. Я смотрел предыдущие вопросы и ответы, но ни один из них не соответствовал моему желаемому результату.
У меня есть два файла с разделителями-запятыми разной длины file1.csv и file2.csv.
Мне нужно объединить эти файлы на основе их первого поля. Если первое поле из file1.csv присутствует в file2.csv, то соответствующая строка из file2.csv должна быть добавлена к строке file1.csv. Если 1-го поля нет, то строка из file1.csv должна быть напечатана, а no match добавлена к ней.
file1.csv (4 столбца):
Contig_Spider_Gland_98_1_1,>Contig_Spider_Gland_98_1_1 [1169 - 963] (REVERSE SENSE),MQGHRRKLATPRQRAPRKERQRALLLRLQWRIGLQPCSRRNKSLDRKNIYWRYLVEYGSWKGRTHISDV,C#
Contig_Spider_Gland_98_7_3,>Contig_Spider_Gland_98_17965_1 [90 - 278],MADVEKTSCCTETKECCKDETCCENGQGACHTGKEECKDTCHKKACGCKAGEDCKCSDGKCGC,CC#CC#CC#C#C#C#C#C#C#C#C#C#
file2.csv (7 столбцов):
Contig_Spider_Gland_98_1_1, SignalP-4.1, SIGNAL, 1, 22, 0.808, YES
Contig_Spider_Gland_98_8_2, SignalP-4.1, SIGNAL 1, 20, 0.877, YES
Желаемый результат:
Contig_Spider_Gland_98_1_1,>Contig_Spider_Gland_98_1_1 [1169 - 963] (REVERSE SENSE),MQGHRRKLATPRQRAPRKERQRALLLRLQWRIGLQPCSRRNKSLDRKNIYWRYLVEYGSWKGRTHISDV,C#,Contig_Spider_Gland_98_1_1, SignalP-4.1, SIGNAL, 1, 22, 0.808, YES
Contig_Spider_Gland_98_7_3,>Contig_Spider_Gland_98_17965_1 [90 - 278],MADVEKTSCCTETKECCKDETCCENGQGACHTGKEECKDTCHKKACGCKAGEDCKCSDGKCGC,CC#CC#CC#C#C#C#C#C#C#C#C#C#,no match
Это должно быть сделано (сокращенное (R) и фиксированное (TM) by terdon):
#!/usr/bin/perl
use strict;
use warnings;
@ARGV==2 || die;
open(my $file1, $ARGV[0]) || die("Could not open \"$ARGV[0]\": $!");
open(my $file2, $ARGV[1]) || die("Could not open \"$ARGV[1]\": $!");
$"=","; #" (this comment exists only to prevent syntax hilighting from breaking)
while(my $l1 = <$file1>) {
chomp($l1);
my @f1 = split(",", $l1);
if(my $l2 = <$file2>) {
chomp($l2);
my @f2 = split(",", $l2);
if($f1[0] eq $f2[0]) {
print("@f1,@f2\n");
}
else {
push(@f1, "no_match");
seek($file2, -length($l2), 1);
print("@f1\n");
}
}
else {
push(@f1, "no_match");
print("@f1\n");
}
}
close($file1);
close($file2);
exit;
Поскольку файлы отсортированы, «file1.csv» является надмножеством «file2.csv» и в обоих файлах нет дубликатов строк:
Сравнивает следующие строки в обоих файлах; Если первое поле строки из «file1.csv» соответствует первому полю строки из «file2.csv», добавляет строку из «file2.csv» в строку из «file1.csv» (разделенная запятой) и печатает сгенерированную строку; иначе добавляет поле «no_match» в строку из «file1.csv», возвращает одну строку в «file2.csv» и печатает измененную строку из «file1.csv»; Если «file2.csv» не имеет больше строк, добавляет поле «no_match» в строку из «file1.csv» и печатает измененную строку из «file1.csv».Другим вариантом является использование join:
join -t, file1.csv file2.csv -a 1 -o auto -e 'no match'
Если входные файлы еще не отсортированы, вы можете сделать это за один раз:
join -t, <(sort file1.csv) <(sort file2.csv) -a 1 -o auto -e 'no match'
Exlanation [!d2 ] -t, устанавливает разделитель полей -a 1, чтобы гарантировать, что все распечатываемые строки также напечатаны. -o auto устанавливает выходной формат -e 'no match' заменяет отсутствующие поля ввода «нет соответствия», оператор <(list) подключает выход команд сортировки для именованных каналов, которые затем используются в качестве файлов для команды соединения (под названием «Замена процесса»)