Объединять файлы, используя общий столбец

8

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

файл 1:

a 111 
b 222 
c 333 
d 666 
e 777 

файл 2:

111 x1  
222 x2
333 x3
444 x4 
555 x5 
666 x6 
777 x7 
888 x8

Я хотел бы объединить их следующим образом:

111  x1  a
222  x2  b
333  x3  c
444  x4  0
555  x5  0
666  x6  d
777  x7  e
888  x8  0

Замечания:

Второй столбец файла 1 является подмножеством первого столбца файла 2

gforce89
источник

Ответы:

7

Команда joinделает почти то, что вам нужно, если файлы отсортированы, как в ваших примерах:

join -12 -a2 file1 file2 -o2.1,2.2,1.1

Вам просто нужно добавить нули к строкам без совпадения. Вы можете использовать -eпереключатель для этого:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0
choroba
источник
если вы добавите -e0не нужно Perl :)
LilloX
@LilloX: правда, спасибо. Я пытался, но не получилось (опечатка).
Чороба
13

Используя соединение:

join -1 1 -2 2 -a1 -e0 -o'0,1.2,2.1' file2 file1

Команда join объединяет строки двух файлов, которые имеют общее поле данных. В этом случае: Соедините файл2 и файл1, используя поле 1 ( -1 1) файла2 и поле 2 ( -2 2) файла1.

Выводом будет: «объединенное поле, поле 2 файла2, поле 1 файла1» ( -o'0,1.2,2.1'), если пропущенное поле занято 0 ( -e0)

Если в одном из двух файлов больше записей, добавьте их (в данном случае file2) ( -a1)

Пожалуйста, обратитесь к man-странице команды join

LilloX
источник
Хорошо. Не могли бы вы добавить немного объяснений?
Лети
Конечно, Обновлено :)
LilloX
5

Немного awkмагии:

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0}; \
    printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}' \
    file1 file2

или

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

Вывод

111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

объяснение

  • FNR==NR{a[$2]=$1;next}

    Запускает over file1( FNR==NR) и создает структуру ключ-значение. Ключ - второй столбец ( $2) file1, значение - первый столбец ( $1)file1

  • {if(a[$1]==""){a[$1]=0};print $1,$2,a[$1]}

    Пробегает file2и

    • if(a[$1]==""){a[$1]=0}

      Если ключ в первом столбце ( $1) в file2не существует в file1, нам нужно0

    • print $1,$2,a[$1]

      Выведите (используя print) первый и второй столбцы file2и значение структуры ключ-значение с ключом первого столбца ( $1) изfile2

      или

    • printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}'

      Выведите (используя printf) первый и второй столбцы file2и значение структуры ключ-значение с ключом первого столбца ( $1) из file2.

      • FS разделитель между столбцами, взятый из входного файла

      • "%s%s%s%s%s\n"

        форматирование для вывода

        • %s - Строка

        • \n - Новая линия

AB
источник
Не могли бы вы объяснить код?
gforce89
Конечно, ответ обновлен.
AB
1

Используя q :

$ q "select f2.c1, f2.c2, ifnull(f1.c1,0) from file_2.txt f2 LEFT JOIN file_1.txt f1 on f1.c2 = f2.c1 "
111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Иногда это может быть более читабельным.

Vi.
источник
1
Для всех, кто интересуется, qесть в пакете python3-q-text-as-data(Python 3) и в пакете python-q-text-as-data(Python 2).
Кос
Спасибо, но где я могу получить этот qпакет? Я , кажется, не быть в состоянии установить либо python-q-text-as-dataили python3-q-text-as-data. Msgstr "E: Невозможно найти пакет python3-q-text-as-data". Моя система уже установлена python, python2.7, python3и python3.4.
Пэдди Ландау
Возможно, пакет слишком новый и недоступен в вашем выпуске. Вы можете клонировать его Github: github.com/harelba/q
Vi.