присоединитесь 3 файла первым Столбцом с соединением (был awk)?

у меня есть три подобных файла, они все как это:

Файл A

ID1 Value1a
ID2 Value2a
  .
  .
  .
IDN Value2n

и я хочу вывод как это

Вывод

ID1 Value1a Value1b Value1c
ID2 Value2a Value2b Value2c
.....
IDN ValueNa ValueNb ValueNc

Обращаясь к первой строке, я хочу, чтобы value1A был значением id1 в fileA, value1B значение id1 в fileB, и так далее который каждое поле и каждая строка. Я думал это как соединение sql. Я попробовал несколько вещей, но ни один из них, где даже закрываются.

Править: Все файлы имеют ту же длину и идентификаторы.

7
задан msemelman 25 June 2010 в 15:33
поделиться

4 ответа

Дайте join(1) попробуйте:

join fileA fileB | join - fileC
10
ответ дан 6 December 2019 в 14:01
поделиться

join (ответ Денниса) лучше, но просто для удовольствия, вот что я придумал в awk :

awk '{a=$0; getline b <"fileB"; getline c <"fileC"; $0=a" "b" "c; print $1,$2,$4,$6}' <fileA
2
ответ дан 6 December 2019 в 14:01
поделиться

Обновление: Вопрос был отредактирован, чтобы указать, что все файлы содержат все ключи, поэтому принятый ответ ( join ) определенно лучше, чем этот. Используйте его только в том случае, если возможно, ключи могут быть не во всех файлах.


Если вы не слишком озабочены производительностью, вы можете попробовать быстрое и грязное:

$ cat file_a
    ID5 Value5a
    ID1 Value1a
    ID3 Value3a
    ID4 Value4a
    ID2 Value2a
$ cat file_b
    ID1 Value1b
    ID3 Value3b
$ cat file_c
    ID2 Value2c
    ID3 Value3c
    ID4 Value4c
    ID5 Value5c
$ cat qq.sh
    #!/bin/bash
    keylist=$(awk '{print $1'} file_[abc] | sort | uniq)
    for key in ${keylist} ; do
        val_a=$(grep "^${key} " file_a | awk '{print $2}') ; val_a=${val_a:--}
        val_b=$(grep "^${key} " file_b | awk '{print $2}') ; val_b=${val_b:--}
        val_c=$(grep "^${key} " file_c | awk '{print $2}') ; val_c=${val_c:--}
        echo ${key} ${val_a} ${val_b} ${val_c}
    done
$ ./qq.sh
    ID1 Value1a Value1b -
    ID2 Value2a - Value2c
    ID3 Value3a Value3b Value3c
    ID4 Value4a - Value4c
    ID5 Value5a - Value5c

На самом деле это сначала обрабатывает ключи, а затем получает значения из каждого файла с этим ключом, или - , если его нет в соответствующем файле.

Команды grep должны быть скорректированы, если файл более сложный (если поле 1 не находится в начале строки или за ним следует разделитель без пробела), но это должно быть быть разумным первым решением. Скорее всего, grep для использования в этом случае будет:

grep "^[ X]*${key}[ X]"

где X на самом деле является символом табуляции , так как это позволяет использовать ноль или более пробелов или табуляции перед ключом и пробел или табуляция для завершения ключа.

Если файлы очень большие, вы можете попробовать использовать ассоциативные массивы в awk , но, поскольку размер не указан, я бы начал с этого, пока вы не дойдете до точка, где он работает слишком медленно.

2
ответ дан 6 December 2019 в 14:01
поделиться

Просто добавлю, что для работы соединения входные данные должны быть отсортированы. Это awk-решение должно обрабатывать любое количество входных файлов. Вы также потеряете исходный порядок ключей (вам понадобится больше кода, чтобы сохранить его).

awk 'END {
  for (K in k) print K, k[K]
    }
{ 
  k[$1] = k[$1] ? k[$1] FS $2 : $2 
  }' file1 file2 [.. filen]
1
ответ дан 6 December 2019 в 14:01
поделиться
Другие вопросы по тегам:

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