Вопрос или проблема
Предположим, у вас есть один CSV-файл с 2 полями: ID и email. У вас есть другой файл с 2 полями: email и имя. Как вы можете создать файл со всеми тремя полями, объединенными по email?
Revision3:
Вы должны отсортировать оба списка по email в алфавитном порядке, а затем объединить. Поскольку поле email является 2-м полем первого файла и 1-м полем второго файла:
sort -t , -k 2,2 file1.csv > sort1.csv
sort -t , -k 1,1 file2.csv > sort2.csv
join -t , -1 2 -2 1 sort1.csv sort2.csv > sort3.csv
значения параметров
-t , : ',' является разделителем полей -k 2,2 : сортировка по 2-му полю -k 1,1 : сортировка по 1-му полю -1 2 : файл 1, 2-е поле -2 1 : файл 2, 1-е поле > : вывод в файл
получается
email,ID,name email,ID,name ...
отсортированных по email в алфавитном порядке.
Обратите внимание, что если какой-либо email отсутствует в любом из файлов, он будет исключён из результатов.
Используйте csvkit:
csvjoin -c email id_email.csv email_name.csv
или
csvjoin -c 2,1 id_email.csv email_name.csv
Возможно, это избыточно, но вы можете импортировать в базу данных
(например, OpenOffice Base) как два типа таблиц и определить
отчет, который будет необходимым выводом.
Если импорт CSV является проблемой, программа для работы с таблицами
(например, OpenOffice Calc) может выполнить импорт. Результат можно
легко передать в базу данных.
На будущее, вы могли бы начать пробовать AWK. Это очень простой язык сценариев, который существует в какой-то форме на каждой системе *nix, и его единственная цель — манипуляция текстовыми базами данных с разделителями. С небольшим количеством одноразового скрипта вы можете сделать некоторые очень полезные вещи. Язык небольшой и элегантный и имеет лучшее соотношение утилита/сложность, чем что-либо еще, о чем я знаю.
Используйте Go: https://github.com/chrislusf/gleam
package main
import (
"flag"
"os"
"github.com/chrislusf/gleam"
"github.com/chrislusf/gleam/source/csv"
)
var (
aFile = flag.String("a", "a.csv", "первый csv файл с 2 полями, первым из которых является ключ")
bFile = flag.String("b", "b.csv", "второй csv файл с 2 полями, первым из которых является ключ")
)
func main() {
flag.Parse()
f := gleam.New()
a := f.Input(csv.New(*aFile))
b := f.Input(csv.New(*bFile))
a.Join(b).Fprintf(os.Stdout, "%s,%s,%s\n").Run()
}
Вы также можете прочитать CSV файл с помощью программы для работы с таблицами, такой как LibreOffice, и использовать макрос VLOOKUP()
для поиска имени во втором файле.
В Bash 5.0.3 с GNU Coreutils 8.30 и ссылаясь на ответ hyperslug:
Если у вас есть неотсортированные CSV файлы с дублирующимися строками и вы не хотите пропускать данные из-за отсутствующего поля в строке любого из file1.csv
или file2.csv
, то вы можете сделать следующее:
Отсортируйте файл 1 по полю 2 и файл 2 по полю 1:
( head -n1 file1.csv && tail -n+2 file1.csv | sort -t, -k2,2 ) > sort1.csv
( head -n1 file2.csv && tail -n+2 file2.csv | sort -t, -k1,1 ) > sort2.csv
Расширяя параметры hyperslug:
-k 2,2 : сортировка символов, начинающаяся и заканчивающаяся на 2-м поле
-k 1,1 : сортировка символов, начинающаяся и заканчивающаяся на 1-м поле
head -n1 : считать первую строку
tail -n+1: : считать все, кроме первой строки
( ) : подсеть
> : вывод в файл
Мне нужно было использовать head
и tail
внутри подсети ( )
, чтобы сохранить первую строку заголовка CSV файла при сортировке по данному полю.
Затем,
join -t , -a1 -a2 -1 2 -2 1 -o auto sort1.csv sort2.csv > sort3.csv
Расширяя параметры hyperslug:
-t , : ',' является разделителем полей
-a1 : Не пропускайте строки из файла 1, если совпадение в файле 2 не найдено
-a2 : Не пропускайте строки из файла 2, если совпадение в файле 1 не найдено.
-1 2 : файл 1, 2-е поле
-2 1 : файл 2, 1-е поле
-o auto : Автоформат: включает дополнительные запятые, указывающие на несовпадающие поля
> : вывод в файл
Вот пример file1.csv
, file2.csv
и результирующего sort3.csv
:
file1.csv
:
ID,email
02,[email protected]
03,[email protected]
05,[email protected]
07,[email protected]
11,[email protected]
file2.csv
:
email,name
[email protected],Timothy Brown
[email protected],Robert Green
[email protected],Raul Vasquez
[email protected],Carol Lindsey
sort3.csv
:
email,ID,name
[email protected],02,Robert Green
[email protected],,Carol Lindsey
[email protected],03,
[email protected],07,Raul Vasquez
[email protected],05,
[email protected],,Timothy Brown
[email protected],11,
Вы можете увидеть, что у Timothy Brown и Carol Lindsey отсутствуют ID, но они все равно включены в объединенный CSV файл (с их именами и email в правильных полях).
Попробуйте CSV Cruncher.
Он принимает CSV файлы в качестве SQL таблиц и затем позволяет выполнять SQL запросы, в результате чего создается другой CSV или JSON файл.
Для вашего случая вы просто вызовете:
crunch -in tableA.csv -in tableB.csv
-out output.csv
-sql "SELECT tableA.id, tableA.email, tableB.name
FROM tableA LEFT JOIN tableB USING (email)"
Инструмент требует Java 11 или более поздней версии.
Некоторые из преимуществ:
- Вы действительно получаете поддержку CSV, а не просто “давайте предположим, что данные верны”.
- Вы можете объединять по нескольким ключам.
- Проще использовать и понимать, чем решения на основе
join
. - Вы можете объединить более 2 CSV файлов.
- Вы можете объединять по SQL выражениям – значения не обязательно должны быть одинаковыми.
Отказ от ответственности: Я написал этот инструмент.
Вы также можете использовать инструмент, специально разработанный для объединения csv файлов, такой как тот, который находится на https://filerefinery.com
Операции, которые мы в настоящее время поддерживаем: Объединение csv файлов. Возможен SQL-эквивалент внешних, внутренних, левых и правых операций соединения на двух csv файлах. Какой столбец будет использоваться в качестве ключа объединения в каждом из файлов, настраивается.
Ответ или решение
Объединение двух CSV файлов – это распространённая задача при работе с данными. Допустим, у вас есть два файла, один с полями ID и email, а другой с полями email и name. В данной статье мы рассмотрим, как объединить эти файлы по полю email, чтобы получить новый файл с тремя полями: email, ID и name.
Шаг 1: Подготовка файлов
Перед тем как начать объединение, важно отсортировать оба файла по полю email. Это необходимо, поскольку команда объединения (join) требует, чтобы файлы были отсортированы.
Воспользуемся командной строкой для сортировки:
sort -t , -k 2,2 file1.csv > sort1.csv
sort -t , -k 1,1 file2.csv > sort2.csv
-t ,
указывает на то, что разделителем является запятая.-k 2,2
обозначает, что сортировка будет проходить по второму полю для первого файла.-k 1,1
– для второго файла по первому полю.
Таким образом, у нас получится два отсортированных файла: sort1.csv
и sort2.csv
.
Шаг 2: Объединение файлов
Теперь можно объединить два отсортированных файла по полю email. Для этого используем команду join:
join -t , -1 2 -2 1 sort1.csv sort2.csv > result.csv
-1 2
указывает, что в первом файле нужно взять второе поле (email).-2 1
указывает на то, что во втором файле нужно взять первое поле (email).> result.csv
направляет вывод в новый файл.
Шаг 3: Обработка отсутствующих данных
В случае, если необходимо оставить все записи из обоих файлов, даже если у одной из записей нет соответствующей записи в другом файле, вы можете использовать параметры -a1
и -a2
:
join -t , -a1 -a2 -1 2 -2 1 -o auto sort1.csv sort2.csv > result.csv
Этот вариант объединения позволит сохранить все данные и избежать потери информации, если для некоторых email не найдется соответствующих записей.
Альтернативные методы
-
Использование csvkit:
Если вы предпочитаете работать с более высокоуровневыми инструментами, используйтеcsvkit
. Эта библиотека Python предоставляет инструменты для работы с CSV файлами:csvjoin -c email id_email.csv email_name.csv > result.csv
-
Базы данных:
Для более сложных сценариев можно импортировать данные в реляционную базу данных и использовать SQL-запросы для объединения данных. Это может быть выполнено через такие инструменты, как OpenOffice Base или другие СУБД. -
Программирование:
Если вы предпочитаете программировать, можно использовать язык Go с библиотекойgleam
для выполнения объединений CSV:package main import ( "flag" "os" "github.com/chrislusf/gleam" "github.com/chrislusf/gleam/source/csv" ) var ( aFile = flag.String("a", "a.csv", "первый csv файл") bFile = flag.String("b", "b.csv", "второй csv файл") ) func main() { flag.Parse() f := gleam.New() a := f.Input(csv.New(*aFile)) b := f.Input(csv.New(*bFile)) a.Join(b).Fprintf(os.Stdout, "%s,%s,%s\n").Run() }
Заключение
Объединение CSV файлов может быть выполнено различными методами: от командной строки до программных решений. Выбор метода зависит от объема данных, ваших предпочтений и доступных инструментов. С помощью описанных выше шагов и инструментов вы сможете успешно объединить два CSV файла по полю email, создавая новый файл, содержащий всю необходимую информацию.