Я хотел бы объединить два файла. Я рассмотрел предыдущие вопросы и ответы, но ни один из них не соответствует моему желаемому выводу.
У меня есть два разделенных от запятой файла различных длин, 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
Это должно сделать это:
awk -F, -vOFS=, '(NR==FNR){a[$1]=$0; next}
{
if(a[$1]){print $0,a[$1]}
else{print $0,"no match"}
}' file2.csv file1.csv
awk -F, -vOFS=,
: выполненный awk
, установка входа (-F
) и вывод (-vOFS=,
) разделители полей к ,
. (NR==FNR){a[$1]=$0; next}
: NR
и FNR
специальные переменные, которые означают текущий номер строки и текущий номер строки текущего файла соответственно. При передаче больше чем одного имени файла эти два будут равны только, в то время как первый файл читается. Так, это означает "при чтении первого файла сохраните каждую строку в массиве, ключ которого является первым полем и перемещением к следующей строке".if(a[$1]){print $0,a[$1]}
: мы находимся теперь во втором файле. Если 1-е поле текущей строки было также в 1-м файле, распечатайте текущую строку и строку из первого файла. else{print $0,"no match"}
: если 1-е поле не было в первом файле, распечатайте текущую строку и "никакое соответствие"Обратите внимание, что я являюсь передающим file2.csv
как первый файл и file1.csv
как второе. Это вызвано тем, что один из этих двух файлов должен храниться в памяти, таким образом, лучше сохранить самый маленький из двух.
Другой выбор состоит в том, чтобы использовать соединение:
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
-t,
устанавливает полевой сепаратор -a 1
, гарантируют, что все unpairable линии напечатаны также -o auto
наборы, выходной формат -e 'no match'
заменяет недостающие поля ввода 'никаким матчем' <(list)
, оператор соединяет продукцию команд вида к названным трубам, которые тогда используются в качестве файлов для команды соединения (названный Заменой Процесса) apt-key
вручную .
– earthmeLon
1 January 2017 в 08:07
Это должно сделать (сократил (R) и зафиксировал (ТМ) 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" и нет никаких дублирующихся строк ни в одном файлов это:
Ctrl+Alt+PrintScreen
поднимает экранную утилиту снимка на моей Беспроводной связи клавиатура Logitech K800.
– WinEunuuchs2Unix
1 January 2017 в 16:31
grep -RPis '(?<!mou)ntp' /var/log
показал эти 14 строк системного журнала , показав синхронизации времени от хоста, который, оказывается, имеетntp
на его имя. В ретроспективе, это имеет смысл, что таинственный сервис, я никогда не знал, что имел, была часть systemd. (Btw, положительная сторона у chrony, который я hadn' t проверенный на также; it' s не установленный, все же.) – Eliah Kagan 3 January 2017 в 05:09