как объединить 2 файла, если данные совпадают между 2 файлами

Вопрос или проблема

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

файл1:

7451,0831,N,L
6723,879,K,L

файл2:

7451,0831,XC,N,,224,
6482,1234,XC,P,1,234

файл2 может иметь разное количество записей, файл1 постоянен.

Вывод:

7451,0831,N,L,7451,0831,XC,N,,224,

Я пробовал следующую команду awk, но, похоже, она выводит только совпадение из файла2

awk -F ',' 'NR==FNR{a[$1,$2];next} ($1,$2) in a { print a[$1],a[$2],$0}' \
    файл1 файл2

Если бы вам не нужно было повторять ключ перед полями файла2, это было бы намного проще:

join -t, <(LC_COLLATE=C sort файл1) <(LC_COLLATE=C sort файл2)

Однако, поскольку вам нужно повторять ключ перед полями файла2, вам придется указать пользовательский формат вывода для join, что требует перечисления необходимых полей из каждого файла, что, в свою очередь, требует знания, сколько полей включить из файла1 / файла2.

Поскольку количество полей варьируется среди записей файла2, вам нужно будет включить количество полей, равное количеству полей в записи с наибольшим количеством полей в файле2, в строку формата вывода join, чтобы это сработало.

Используя Awk и умный метод (если я сам так считаю) для автоматической генерации списка полей, которые нужно включить из файла2, вы можете сделать:

nf2=$(awk -F, '{NF>mnf && mnf=NF} END {print mnf}' файл2)
f2of=( 2.{1..${nf2}} )
join -t, -o 1.{1..4} ${f2of[@]} <(LC_COLLATE=C sort файл1) <(LC_COLLATE=C sort файл2)
  • Команда Awk выведет количество полей в записи с наибольшим количеством полей в файле2
  • f2of=( 2.{1..${nf2}} ) автоматически сгенерирует список полей для включения из файла2, расширив nf2 в 2.1 2.2 2.3 ... 2.nf2
% cat файл1
6723,879,K,L
7451,0831,N,L
% cat файл2
7451,0831,XC,N,,224,
6482,1234,XC,P,1,234
% nf2=$(awk -F, '{NF>mnf && mnf=NF} END {print mnf}' файл2)
f2of=( 2.{1..${nf2}} )
join -t, -o 1.{1..4} ${f2of[@]} <(LC_COLLATE=C sort файл1) <(LC_COLLATE=C sort файл2)
7451,0831,N,L,7451,0831,XC,N,,224,

$ join -t ',' файл1 файл2
7451,0831,N,L,0831,XC,N,,224,

Ответ или решение

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

Описание задачи

У нас есть два входных файла:

  1. file1:

    7451,0831,N,L
    6723,879,K,L
  2. file2:

    7451,0831,XC,N,,224,
    6482,1234,XC,P,1,234

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

Ожидаемый вывод

Мы ожидаем, что при нахождении совпадений в первых двух полях каждого файла, будет сформирована строка, содержащая поля из обоих файлов:

7451,0831,N,L,7451,0831,XC,N,,224,

Подход к решению

Для решения рекомендуем использовать команду join в Unix/Linux, однако учитывая, что необходимо повторить ключ перед полями из file2, нужно учитывать количество полей в записи, самой длинной из file2.

Шаги по реализации

  1. Сортировка файлов: Чтобы использовать команду join, требуется произвести предварительную сортировку обоих файлов.
  2. Определение количества полей: Мы можем использовать awk для определения максимального количества полей в file2.
  3. Формирование команд: Сформируем команду join, которая будет выводить в нужном формате данные из обоих файлов.

Пример реализации

# Определяем максимальное количество полей в file2
nf2=$(awk -F, '{NF > mnf && mnf = NF} END {print mnf}' file2)

# Автоматически генерируем список полей для file2
f2of=( 2.{1..${nf2}} )

# Выполняем join, используя автоматическую генерацию
join -t, -o 1.{1..4} ${f2of[@]} <(LC_COLLATE=C sort file1) <(LC_COLLATE=C sort file2)

Объяснение команд

  • awk -F, '{NF > mnf && mnf = NF} END {print mnf}' file2 — Эта команда определяет максимальное количество полей во всех записях file2.

  • f2of=( 2.{1..${nf2}} ) — Здесь мы генерируем массив, который будет содержать ссылки на все поля из file2, начиная с первого.

  • Команда join с параметрами -o определяет, какие поля выводить из каждого файла. Мы используем автоматическую генерацию полей из второго файла, делая процесс более универсальным.

Примечание

Важно отметить, что для корректной работы команда join требует предварительной сортировки файлов, поэтому используем конструкции <(LC_COLLATE=C sort ...), чтобы выполнять сортировку "на лету".

Этот подход хорошо зарекомендовал себя в условиях работы с большими количествами данных и позволяет эффективным образом обрабатывать файлы с различным количеством записей.

Оцените материал
Добавить комментарий

Капча загружается...