Предположим, что у меня есть два файла: en.csv
и sp.csv
, каждый из которых содержит ровно две записи, разделенные запятыми:
en.csv
:
1,dog,red,car
3,cat,white,boat
sp.csv
:
2,conejo,gris,tren
3,gato,blanco,bote
Если я выполняю
join -t, -a 1 -a 2 -e MISSING en.csv sp.csv
вывод, который я получаю:
1,dog,red,car
2,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
Обратите внимание, что все отсутствующие поля были свернуты. Чтобы получить "правильное" полное внешнее соединение, мне нужно указать формат; Таким образом,
join -t, -a 1 -a 2 -e MISSING -o 0,1.2,1.3,1.4,2.2,2.3,2.4 en.csv sp.csv
дает
1,dog,red,car,MISSING,MISSING,MISSING
2,MISSING,MISSING,MISSING,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
Одним из недостатков этого способа создания полного внешнего соединения является то, что нужно явно указать формат финальной таблицы, что может быть нелегко сделать в программных приложениях (где идентификация объединенных таблиц известна только при во время выполнения).
Последние версии GNU join
устраняют этот недостаток, поддерживая специальный формат auto
. Поэтому с такой версией join
последняя команда выше может быть заменена гораздо более общей
join -t, -a 1 -a 2 -e MISSING -o auto en.csv sp.csv
Как я могу добиться такого же эффекта с версиями join
, которые не поддерживают параметр -o auto
?
Фон и сведения
У меня есть оболочка Unix (zsh) script, которая предназначена для обработки нескольких CSV файлов, и делает это, широко используя опцию GNU join
-o auto. Мне нужно изменить этот script так, чтобы он работал в средах, где доступная команда join
не поддерживает параметр -o auto
(как в случае с BSD join
, так и для более старых версий GNU join
).
Типичное использование этой опции в script выглядит примерно так:
_reccut () {
cols="1,$1"
shift
in=$1
shift
if (( $# > 0 )); then
join -t, -a 1 -a 2 -e 'MISSING' -o auto \
<( cut -d, -f $cols $in | sort -t, -k1 ) \
<( _reccut "[email protected]" )
else
cut -d, -f $cols $in | sort -t, -k1
fi
}
Я показываю этот пример, чтобы проиллюстрировать, что было бы трудно заменить -o auto
на явный формат, поскольку поля для включения в этот формат неизвестны до выполнения.
Функция _reccut
выше в основном извлекает столбцы из файлов и объединяет результирующие таблицы вдоль их первого столбца. Чтобы увидеть, как _reccut
в действии, представьте, что помимо файлов, упомянутых выше, у нас также был файл
de.csv
2,Kaninchen,Grau,Zug
1,Hund,Rot,Auto
Затем, например, чтобы отобразить бок о бок столбца 3 из en.csv
, столбцы 2 и 4 из sp.csv
и столбец 3 команды de.csv будут запускаться:
% _reccut 3 en.csv 2,4 sp.csv 3 de.csv | cut -d, 2-
red,MISSING,MISSING,Rot
MISSING,conejo,tren,Grau
white,gato,bote,MISSING