Объединение двух таблиц, включая многократное появление идентификаторов столбцов и уникальных строк

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

Я хотел бы объединить две таблицы на основе столбца 1:

Файл 1:

1 сегодня
1 зеленый
2 завтра
3 красных

Файл 2:

1 много
1 иногда
2 на работе
2 дома
2 иногда
3 новых
4 много
5 иногда
6 на работе

Желаемый вывод (файл 3):

1 сегодня много
1 сегодня иногда
1 зеленый много
1 зеленый иногда
2 завтра на работе
Завтра у себя дома
2 завтра иногда
3 новых новых

Я придумал следующее:

awk -F '[\t]' -v OFS='\t' '{i=$1;$1=x} NR==FNR{A[i]=$0;next} A[i]{print i,$0A[i]}' file2 file1 > file3 

Однако это дает мне только:

1 сегодня иногда
2 завтра иногда
3 новых новых

Обратите внимание, что решения в предыдущем потоке (join и awk) дали бы мне комбинацию из 2 файлов, включая все строки. Я хотел бы иметь только строки файла 1 (столбец 1 в качестве идентификатора), но сообщать обо всех совпадениях в файле 2.

Редактировать:

столбцы разделены на вкладку

Реальный файл 1: fig | 395961.4.peg.2627 Бактерии Cyanobacteria неизвестно неизвестно 1795

(Столбец 1: рис … Столбец2: Бактерии … Столбец3 1795)

Реальный файл 2: fig | 1000561.3.peg.1838 Cysteine ​​desulfurase (EC 2.8.1.7) Тест – тиамин-кофакторы, витамины, протезные группы, пигменты

(Столбец1: fig … Column2: Cysteine ​​… Column3 Test …)

3 Solutions collect form web for “Объединение двух таблиц, включая многократное появление идентификаторов столбцов и уникальных строк”

Я бы сделал это в Perl:

 #!/usr/bin/env perl use strict; my (%file1,%file2); ## Open the 1st file open(A,"file1"); while(<A>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## This is the tricky part. It adds fields 2-last ## to the hash $file1. The value of this hash is an array ## and the keys are the 1st fields. This will result in a list ## of all 1st fields and all their associated columns. push @{$file1{$F[0]}},@F[1..$#F]; } ## Open the 2nd file open(B,"file2"); while(<B>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## If the current 1st field was found in file1 if (defined($file1{$F[0]})) { ## For each of the columns associated with ## this 1st field in the 1st file. foreach my $col (@{$file1{$F[0]}}) { print "$F[0]\t$col\t@F[1..$#F]\n"; } } } в #!/usr/bin/env perl use strict; my (%file1,%file2); ## Open the 1st file open(A,"file1"); while(<A>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## This is the tricky part. It adds fields 2-last ## to the hash $file1. The value of this hash is an array ## and the keys are the 1st fields. This will result in a list ## of all 1st fields and all their associated columns. push @{$file1{$F[0]}},@F[1..$#F]; } ## Open the 2nd file open(B,"file2"); while(<B>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## If the current 1st field was found in file1 if (defined($file1{$F[0]})) { ## For each of the columns associated with ## this 1st field in the 1st file. foreach my $col (@{$file1{$F[0]}}) { print "$F[0]\t$col\t@F[1..$#F]\n"; } } } в #!/usr/bin/env perl use strict; my (%file1,%file2); ## Open the 1st file open(A,"file1"); while(<A>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## This is the tricky part. It adds fields 2-last ## to the hash $file1. The value of this hash is an array ## and the keys are the 1st fields. This will result in a list ## of all 1st fields and all their associated columns. push @{$file1{$F[0]}},@F[1..$#F]; } ## Open the 2nd file open(B,"file2"); while(<B>){ ## Remove trailing newlines chomp; ## Split the current line on tabs into the @F array. my @F=split(/\t/); ## If the current 1st field was found in file1 if (defined($file1{$F[0]})) { ## For each of the columns associated with ## this 1st field in the 1st file. foreach my $col (@{$file1{$F[0]}}) { print "$F[0]\t$col\t@F[1..$#F]\n"; } } } 

Вы могли бы поиграть в него (длинный) с одним лайнером:

 $ perl -lane 'BEGIN{open(A,"file1"); while(<A>){chomp; @F=split(/\t/); push @{$k{$F[0]}},@F[1..$#F];} } $k{$F[0]} && print "$F[0]\t@{$k{$F[0]}}\t@F[1..$#F]"' file2 1 today green a lot 1 today green sometimes 2 tomorrow at work 2 tomorrow at home 2 tomorrow sometimes 3 red new в $ perl -lane 'BEGIN{open(A,"file1"); while(<A>){chomp; @F=split(/\t/); push @{$k{$F[0]}},@F[1..$#F];} } $k{$F[0]} && print "$F[0]\t@{$k{$F[0]}}\t@F[1..$#F]"' file2 1 today green a lot 1 today green sometimes 2 tomorrow at work 2 tomorrow at home 2 tomorrow sometimes 3 red new 

Если вы работаете с огромными файлами, пусть это работает.

Использование awk

ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ

Четкий:

  awk 'function get(file,x,y) { while ( (getline < file) > 0) {if ($1==x)y,substr($0,index($0," ")+1)} close(file) } ARGV[1]==FILENAME{get(ARGV[2],$1,$0)}' file1 file2 

Одна линия:

 awk 'function g(f,x,y){while((getline <f)>0)if($1==x){print y,substr($0,index($0," ")+1)}close(f)}NR==FNR{g(ARGV[2],$1,$0)}' file1 file2 

,

ИСПОЛЬЗОВАНИЕ МАССЫ

 awk 'FNR==NR{a[$0]=$1;next}{for(i in a)if(a[i]==$1)print i,substr($0,index($0," ")+1)}' file file2 

,

РЕЗУЛЬТАТ

 1 today a lot 1 today sometimes 1 green a lot 1 green sometimes 2 tomorrow at work 2 tomorrow at home 2 tomorrow sometimes 3 red new 

Что случилось с командой соединения?

join file1 file2

Дает требуемый результат

  • Awk сравнивает 2 файла, распечатывает совпадение вместе с несоответствующими строками, заполненными 0
  • Присоединить два несортированных файла к POSIX?
  • Использование grep / awk / sed для сортировки и объединения двух файлов
  • Объединение нескольких файлов с присоединением
  • Вставить несколько файлов на основе первого столбца в один файл
  • vlookup работать в awk на linux
  • слияние файлов и получение значений столбцов на основе поля id
  • присоединить несколько строк на основе столбца1
  • Присоединить (большие) файлы по алфавитно-цифровому шаблону
  • Объединение двух файлов, соответствующих двум столбцам с несоответствиями и в каждой соответствующей строке, замените второй столбец из файла 1 на 6-й столбец в файле 2
  • Объединение строк с одинаковым полем
  • Linux и Unix - лучшая ОС в мире.