Сценарий оболочки для объединения двух файлов

8

Я хочу написать, shell scriptчто получить два файла Aи B, и получить результат, как это:

Файл A:

user_a tel_a addr_a
user_b tel_b addr_b

Файл B:

process_1 user_a
process_2 user_a
process_3 user_b

И результат:

user_a process_1 tel_a addr_a
user_a process_2 tel_a addr_a
user_b process_3 tel_b addr_b

Как я могу это сделать? awkили что-то другое?

Навид Фархади
источник
2
Я думаю, что это может быть сделано с помощью cutи pasteтолько, но я не понимаю синтакс правильно.
Бернхард
Мои файлы имеют много записей и полей, я не могу вырезать и вставить! Это всего лишь образец.
Навид Фархади
1
@NavidFarhadi not cut & paste: есть две фактические команды cutи pasteпосмотрите на их страницу руководства.
Маттео
Я могу загрузить оба файла в память полностью, и я также могу использовать awk.
Навид Фархади
Я также могу использовать Perl или другие, если они были исполняемыми в командной строке Linux.
Навид Фархади

Ответы:

15

join ...

join -1 2 -2 1 FileB FileA

Вывод

user_a process_1 tel_a addr_a
user_a process_2 tel_a addr_a
user_b process_3 tel_b addr_b

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

join -1 2 -2 1 <(sort -k2 FileB) <(sort FileA)
Peter.O
источник
Что значит числовые параметры?
Навид Фархади
5
@Navid: Вы всегда можете получить лучшее и наиболее точное описание параметров команды, обратившись к руководству , введя man joinв командной строке терминала ... -1 2   -2 1 означает: присоединиться к «1-му файлу, 2-му полю» и « 2nd-file 1st-field '
Peter.O
3

Так joinи pasteне везде (они не на моей BusyBox основе системы, например), вот как это сделать с AWK, в соответствии с просьбой:

awk 'BEGIN {
    while( (getline < "fileA") > 0) A[$1]=$2 OFS $3 # read fileA into the array A
    close("fileA")
  } {
    print $2, $1, A[$2]
  }' fileB
dubiousjim
источник
Кстати, вы пропустили разделитель A[$1]=$2 OFS $3... Вот еще один вариант, который избегает ручного цикла в BEGIN, но это почти то же самое (к awk ), хотя он вводит ненужный тест условия для второго файла: awk 'NR==FNR {A[$1]=$2 OFS $3;next} {print $2, $1, A[$2]}' fileA fileB... (+ 1)
Peter.O