Команда для выполнения полного внешнего соединения с дублирующимися записями в столбце ключ / соединение - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть три файла.Мне нужно объединить их на основе одного столбца и выполнить некоторые преобразования.

file1.dat (столбец 1 используется для объединения)

123,is1,ric1,col1,smbc1  
123,is2,ric1,col1,smbc1  
234,is3,ric3,col3,smbc2  
345,is4,ric4,,smbc2  
345,is4,,col5,smbc2 

file2.dat (для объединения используется столбец 1)

123,abc  
234,bcd  

file3.dat (для объединения используется столбец 4)

r0c1,r0c2,r0c3,123,r0c5,r0c6,r0c7,r0c8  
r2c1,r2c2,r2c3,123,r2c5,r2c6,r2c7,r2c8  
r3c1,r3c2,r3c3,234,r3c5,r3c6,r3c7,r3c8  
r4c1,r4c2,r4c3,345,r4c5,r4c6,r4c7,r4c8   

Ожидаемый результат(output.dat)

123,r0c5,is1,ric1,smbc1,abc,r0c8,r0c6,col1,r0c7,r0c1,r0c2,r0c3  
123,r0c5,is2,ric1,smbc1,abc,r0c8,r0c6,col1,r0c7,r0c1,r0c2,r0c3  
123,r2c5,is1,ric1,smbc1,abc,r2c8,r2c6,col1,r2c7,r2c1,r2c2,r2c3  
123,r2c5,is2,ric1,smbc1,abc,r2c8,r2c6,col1,r2c7,r2c1,r2c2,r2c3  
234,r3c5,is3,ric3,smbc2,bcd,r3c8,r3c6,col3,r3c7,r3c1,r3c2,r3c3  
345,r4c5,is4,ric4,smbc2,N/A,r4c8,r4c6,N/A,r4c7,r4c1,r4c2,r4c3  
345,r4c5,is4,N/A,smbc2,N/A,r4c8,r4c6,col5,r4c7,r4c1,r4c2,r4c3 

Я написал следующую команду awk.

awk '
BEGIN {FS=OFS=","}
FILENAME == ARGV[1] { temp_join_one[$1] = $2"|"$3"|"$4"|"$5; next}
FILENAME == ARGV[2] { exchtbunload[$1] = $2; next}
FILENAME == ARGV[3] { s_temp_join_one = temp_join_one[$4];
split(s_temp_join_one, array_temp_join_one,"|");
v3=(array_temp_join_one[1]==""?"N/A":array_temp_join_one[1]);
v4=(array_temp_join_one[2]==""?"N/A":array_temp_join_one[2]);
v5=(array_temp_join_one[4]==""?"N/A":array_temp_join_one[4]);
v6=(exchtbunload[$4]==""?"N/A":exchtbunload[$4]);
v9=(array_temp_join_one[3]==""?"N/A":array_temp_join_one[3]);
v11=($2=""?"N/A":$2);
print $4, $5, v3, v4, v5, v6, $8, $6, v9, $7, $1, v11, $3 >
"output.dat" }
' file1.dat file2.dat file3.dat

Мне нужно объединить все три файла.

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

Но моя проблема в том, что ключ не уникален, я не получаю ожидаемый результат.Мой вывод имеет только три строки.

Я пытался применить решение, предложенное с использованием условия соединения.Работает с небольшими файлами.Но у меня есть файлы размером около 3-5 ГБ.И они в числовом, а не лексикографическом порядке.Их сортировка выглядит так, как будто это заняло бы много времени.

Любое предложение будет полезно.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Мне действительно нравится ответ, используя join, но он требует, чтобы файлы сортировались по ключевому столбцу. Вот версия, которая не имеет этого ограничения. Работая в соответствии с теорией, согласно которой лучшим инструментом для работы с базами данных является база данных, он импортирует файлы CSV в таблицы временной базы данных SQLite, а затем запускает для них SELECT, чтобы получить желаемый результат:

(редактировать: пересмотренная версия на основе новой информации о данных)

#!/bin/sh
# Usage: ./merge.sh file1.dat file2.dat file3.dat  > output.dat
file1=$1
file2=$2
file3=$3

rm -f scratch.db
sqlite3 -batch -noheader -csv -nullvalue "N/A" scratch.db  <<EOF | perl -pe 's#(?:^|,)\K""(?=,|$)#N/A#g'
CREATE TABLE file1(f1_1 INTEGER, f1_2, f1_3, f1_4, f1_5);
CREATE TABLE file2(f2_1 INTEGER, f2_2);
CREATE TABLE file3(f3_1, f3_2, f3_3, f3_4 INTEGER, f3_5, f3_6, f3_7, f3_8);
.import $file1 file1
.import $file2 file2
.import $file3 file3
-- Build indexes to speed up joining and sorting gigs of data.
CREATE INDEX file1_idx ON file1(f1_1);
CREATE INDEX file2_idx ON file2(f2_1);
CREATE INDEX file3_idx ON file3(f3_4);
SELECT f3_4, f3_5, f1_2, f1_3, f1_5, f2_2, f3_8, f3_6, f1_4, f3_7, f3_1
     , f3_2, f3_3
FROM file3
LEFT JOIN file1 ON f1_1 = f3_4
LEFT JOIN file2 ON f2_1 = f3_4
ORDER BY f3_4;
EOF
rm -f scratch.db

Примечание: при этом будет использоваться временный файл базы данных, размер которого будет соответствовать всем вашим данным, а затем - некоторым из-за индексов. Если у вас ограниченное пространство, у меня есть идея сделать это без временных файлов, учитывая информацию о том, что объединяемые столбцы отсортированы численно, но это достаточно работы, которую я не буду беспокоить, если не спросят.

0 голосов
/ 16 ноября 2018

с join, при условии, что файлы отсортированы по ключу.

$ join -t, -1 1 -2 4 <(join -t, -a1 -a2 -e "N/A" -o1.1,1.2,1.3,1.4,1.5,2.1 file1 file2) \
  file3 -o1.1,2.5,1.2,1.3,1.5,1.6,2.8,2.6,1.4,2.7,2.2,2.3

123,r0c5,is1,ric1,smbc1,123,r0c8,r0c6,col1,r0c7,r0c2,r0c3
123,r2c5,is1,ric1,smbc1,123,r2c8,r2c6,col1,r2c7,r2c2,r2c3
123,r0c5,is2,ric1,smbc1,123,r0c8,r0c6,col1,r0c7,r0c2,r0c3
123,r2c5,is2,ric1,smbc1,123,r2c8,r2c6,col1,r2c7,r2c2,r2c3
234,r3c5,is3,ric3,smbc2,234,r3c8,r3c6,col3,r3c7,r3c2,r3c3
345,r4c5,is4,ric4,smbc2,N/A,r4c8,r4c6,N/A,r4c7,r4c2,r4c3
345,r4c5,is4,N/A,smbc2,N/A,r4c8,r4c6,col5,r4c7,r4c2,r4c3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...