Как объединить несколько файлов на основе идентификатора в большую матрицу с помощью bash?

У меня есть сотни файлов в каталоге с именами File1, File2, File3, ..., File200. Предположим, у меня сейчас только 3 файла, содержимое этих файлов:

File1: (столбцы разделены табуляцией)

[CITY]  [SCORE]
City1    110
City2    120
City3    130
City4    140

File2: (столбцы разделены табуляцией)

[CITY]  [SCORE]
City1    210
City3    230
City4    240

File3: (столбцы разделены табуляцией)

[CITY]  [SCORE]
City1    310
City5    350

Здесь столбец [CITY] — идентификатор, [SCORE] — значение. Я хочу объединить эти файлы в одну матрицу на основе столбца идентификатора [CITY], заполнив NA недостающие ячейки,

MergedMatrixFile: (столбцы разделены табуляцией)

[CITY]  File1    File2    File3
City1    110    210    310
City2    120    NA    NA
City3    130    230    NA
City4    140    240    NA
City5    NA    NA    350

Как я могу сделать это с Bash.

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

Cyrus 14.12.2020 17:32

Это хороший кандидат на GNU awk. Он имеет многомерные массивы. Вы можете использовать это, чтобы построить матрицу и распечатать ее в блоке END. Обратитесь к awk ​​и нажмите ссылку «Подробнее».

glenn jackman 14.12.2020 17:35

Взгляните на join.

Socowi 14.12.2020 17:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вот довольно уродливый скрипт, который далеко не эффективен и, возможно, содержит ошибки:

#!/bin/bash

TMP=$(mktemp -d)

# get the union of all city names
tail -q -n +2 File* | awk '{print $1}' | sort -u > ${TMP}/cities.txt

# fill in the missing entries for each file
for file in File*; do
    tail -n +2 ${file} | cat - <(diff <(awk '{print $1}' ${file} | sort) ${TMP}/cities.txt | grep '^>') | sed 's/^> \(.*\)/\1    NA/' | sort | awk '{print $2}' > ${TMP}/${file}
done

# put it all together
paste ${TMP}/cities.txt ${TMP}/File* > merged.txt

Спасибо. Тестирую код, основная проблема - потеря имени файла в объединенном файле матрицы.

Jie 15.12.2020 09:29
Ответ принят как подходящий

С awk и возможностью дополнительных файлов

 awk 'FNR > 1 { 
                map[$1][FILENAME]=$2; # Create a two dimensional array with the city as the first index and the filename the second.
                fils[FILENAME] = "" # Create an array of the file names
              } 
          END { 
                PROCINFO["sorted_in"] = "@ind_str_asc"
                printf "%s\t","[CITY]"; # Print the city header
                for (c in fils) { 
                                   printf "%s\t",C# Loop through each file name in fils and print as a header
                                };
                printf "\n";
                for (i in map) { 
                                 printf "%s",i; # Print the city columns
                                 for (j in fils ) { 
                                                     !map[i][j]?str[j] = "NA":str[j]=map[i][j]; # Loop through the two dimensional array and if there is no entry for a given city/file name, set array str to NA (index file name) otherwise set to value in array
                                                     printf "\t%s",str[j] # Print the str variable
                                 } 
                printf "\n" 
                } 
              }' file1 file2 file3

Один лайнер:

awk 'FNR > 1 { map[$1][FILENAME]=$2;fils[FILENAME] = "" } END { PROCINFO["sorted_in"] = "@ind_str_asc";printf "%s\t","[CITY]";for (c in fils) { printf "%s\t",c };printf "\n";for (i in map) { printf "%s",i;for (j in fils ) { !map[i][j]?str[j] = "NA":str[j]=map[i][j];printf "\t%s",str[j] } printf "\n" } }' file1 file2 file3

На самом деле в этом каталоге у меня сотни файлов, а не только 3.

Jie 14.12.2020 18:26

Хорошо, я изменил решение.

Raman Sailopal 14.12.2020 19:22

Спасибо! Небольшая проблема: нам не нужна вкладка \t за последней колонкой

Jie 15.12.2020 09:51

ОК, я изменил расположение табуляции перед строками, а не после них.

Raman Sailopal 15.12.2020 10:30

Еще остались баги. Первая строка в выводе — это [CITY] File2 File3 File1, а не [CITY] File1 File2 File3. причин не узнаю.

Jie 15.12.2020 13:30

Я добавил PROCINFO["sorted_in"] = "@ind_str_asc" в код, чтобы установить порядок массива. Это будет работать только с версиями GNU awk.

Raman Sailopal 15.12.2020 13:37

Привет, кажется, что этот скрипт все еще имеет некоторые ошибки. Когда дело доходит до больших данных, результат неверен. Например, если у меня есть 100 файлов, результаты этого скрипта и другого кода Python будут одинаковыми. Но когда дело доходит до 1000 файлов, результат этого скрипта неверен. Кажется, самый большой объем слитой матрицы из этого скрипта у меня на сервере ~1G. Мне интересно, связана ли проблема с ограничением количества массива в awk.

Jie 16.12.2020 18:44

Другие вопросы по теме