объединение текстовых файлов с разделителями табуляции на основе столбца (который является заголовком) в bash?

У меня есть два текстовых файла, содержащих миллион записей, все записи разделены табуляцией, как мы можем объединить эти два файла на основе одного заголовка (столбец )?

файл: 1

    LogEntryTime              nameId       PartnerId        
    2021-06-05T15:00:53 07    5lsddf        qyutxwr 
        
        

файл: 2

        nameId  GroupId  compnayId
        5lsddf  l4buafm   0rd33cs               
    

вывод примерно так:

    LogEntryTime              nameId       PartnerId    GroupId  compnayId
    2021-06-05T15:00:53 07    5lsddf        qyutxwr     l4buafm   0rd33cs

Пробовал, но не работает:

paste file1.txt file2.txt | nameId -s $'\t' -t

и

cat file1.txt file2.txt |  awk -F '\t' '{print $ list the all columns name here}'

awk один, который работает, но необходимо указать все номера столбцов там.

Есть ли другое решение, которое может мне помочь.

заранее спасибо

0
задан 11 June 2021 в 08:59

3 ответа

Если ваши файлы являются правильно построенными файлами с разделением табуляций (TSV), то вы можете использовать csvjoin из пакета csvkit на базе Python.

Например:

$ head file1.tsv file2.tsv | cat -A
==> file1.tsv <==$
LogEntryTime^InameId^IPartnerId$
2021-06-05T15:00:53 07^I5lsddf^Iqyutxwr$
$
==> file2.tsv <==$
nameId^IGroupId^IcompnayId$
5lsddf^Il4buafm^I0rd33cs$

(cat -A, чтобы сделать вкладки видимыми, как ^I) затем

$ csvjoin -I -t -c nameId file1.tsv file2.tsv
LogEntryTime,nameId,PartnerId,GroupId,compnayId
2021-06-05T15:00:53 07,5lsddf,qyutxwr,l4buafm,0rd33cs

Чтобы получить вывод в формате TSV, используйте csvformat из того же пакета:

$ csvjoin -I -t -c nameId file1.tsv file2.tsv | csvformat -T
LogEntryTime    nameId  PartnerId       GroupId compnayId
2021-06-05T15:00:53 07  5lsddf  qyutxwr l4buafm 0rd33cs

Обратите внимание, что -I отключает вывод типов - который иногда может вести себя неожиданно, особенно с полями datetime.


Еще проще, используя Miller (доступен из репозитория universe, как пакет miller):

$ mlr --tsv join -f file1.tsv -j nameId then reorder -f LogEntryTime file2.tsv
LogEntryTime    nameId  PartnerId       GroupId compnayId
2021-06-05T15:00:53 07  5lsddf  qyutxwr l4buafm 0rd33cs

reorder необходим, потому что по умолчанию mlr join выводит общее поле первым (как и системная команда join). Обратите внимание, что для несортированного ввода в память будет загружен весь file1.tsv.

2
ответ дан 28 July 2021 в 11:30

Запустите один из файлов в массив и замените первое поле второго файла (которое является nameId) на индекс массива, который соотносится с общим полем.

awk -F \\t+ -vOFS=\\t 'NR==FNR{a[$2]=$0;next} {$1=a[$1]}1' file{1,2}.txt
2
ответ дан 28 July 2021 в 11:30

С этим конкретным набором данных:

awk '
    BEGIN {FS = OFS = "\t"}
    NR == FNR {f1[$2] = $0; next}
    {$1 = f1[$1]; print}
' file{1,2}.txt

Упоминается только поле соединения ($ 2 в файле1, $ 1 в файле2).

Производит вывод с разделением табуляцией.

LogEntryTime    nameId  PartnerId   GroupId compnayId
2021-06-05T15:00:53 07  5lsddf  qyutxwr l4buafm 0rd33cs

Для удобного вывода вставьте конвейер в | column -t -s $ '\ t' , чтобы получить

LogEntryTime            nameId  PartnerId  GroupId  compnayId
2021-06-05T15:00:53 07  5lsddf  qyutxwr    l4buafm  0rd33cs
1
ответ дан 28 July 2021 в 11:30

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

Похожие вопросы: