Сравните первый столбец одного файла с первым столбцом второго и напечатайте связанный столбец каждого, если было совпадение - PullRequest
0 голосов
/ 13 ноября 2018

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

Аналогично этому вопросу, но я хотел бы напечатать столбцы из обоих файлов, а не по одному: Как сравнить несколько столбцов в двух файлах и получить соответствующее значение из другого столбца, если совпадение найдено

FILE1.TXT

adeqY   33.7
AIsLX   65.6
AmuBv   1589.0
aZMIx   84.4

file2.txt

AmuBv foo
iwwlp bar
adeqY hi
qUbJZ bye

выход

hi 33.7
foo 1589.0

У меня есть следующая команда awk, но мне удалось напечатать только совпадение второго столбца из File2:

awk 'FNR==NR{a[$1]; next} ($1) in a {print $2 a[$2]}' File1.txt File2.txt

a[$2] не хочет печатать

Заранее спасибо.

Ответы [ 4 ]

0 голосов
/ 14 ноября 2018

Попробуйте Perl вариант

$ cat eskp1.txt
adeqY   33.7
AIsLX   65.6
AmuBv   1589.0
aZMIx   84.4

$ cat eskp2.txt
AmuBv foo
iwwlp bar
adeqY hi
qUbJZ bye

$ perl -F"\s+" -lane 'BEGIN { %kv=map{split /\s+/ } qx(cat eskp1.txt) } { print "$F[1] $kv{$F[0]}" if $kv{$F[0]} } ' eskp2.txt
foo 1589.0
hi 33.7
0 голосов
/ 13 ноября 2018

Не могли бы вы попробовать следующее.

awk 'FNR==NR{a[$1]=$2;next} ($1 in a){print $2,a[$1]}' Input_file1  Input_file2

Вывод будет следующим.

foo 1589.0
hi 33.7

Проблема в вашей попытке: Вы добились успеха только в FNR==NR условии, что ваш a[$1] НЕ имеет никакого значения, он только создал свой индекс в массиве a вот почему он не смог напечатать что-либо во время чтения 2-го Input_file.

0 голосов
/ 13 ноября 2018

То, что вы пытаетесь сделать, это, по сути, ВНУТРЕННЕЕ СОЕДИНЕНИЕ для двух таблиц, хранящихся в текстовых файлах, и команда соединения Linux предназначена именно для этого.

Попробуйте:

join -t' ' -1 1 -2 1 -o 2.2,1.2 <(sort file1.txt) <(sort file2.txt) 
foo 1589.0
hi 33.7

Объяснение:

  • Разделитель полей указывается как -t.Я предположил, что ваши данные разделены одним пробелом в этих текстовых файлах.
  • -1 1 -2 1 говорит, что соединяется в первом поле для файла левой части и в первом поле справаside file.
  • -o 2.2,1.2 определяет поля, которые вы хотите вернуть.Второе поле из второго файла, затем второе поле из первого файла.
  • Наконец, обратите внимание, что я отсортировал входные файлы, поскольку файлы должны быть отсортированы по полю, к которому вы собираетесь присоединиться для Linuxприсоединиться к работе.

Смотрите также этот блог ( ref ).

0 голосов
/ 13 ноября 2018

Здесь происходит следующее: после того, как вы печатаете результаты в последнем операторе awk, массив a[] больше не находится в области видимости, и поэтому второе значение не печатается.

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

for each in $(comm -1 -2 <(awk '{print $1 }' file1.txt | sort ) <(awk '{print $1 }' file2.txt | sort) ); do echo $(grep $each file2.txt | awk '{print $2}') $(grep $each file1.txt | awk '{print $2}') ; done;

Это выводит:

foo 1589.0
hi 33.7

Пояснение:

  • Запустите команду comm для двух файлов.
  • Два «файла», переданные comm, на самом деле замещаются процессом, поэтому они сортируются первыми (comm ожидает отсортированный ввод) и отображается только первый столбец.
  • Параметры -1 -2 для comm предписывают ему печатать только общие элементы из файлов (он может отображать элементы, уникальные для первого файла, уникальные для второго файла или общие для обоих)
  • Как только у вас есть общие элементы из обоих файлов, for each из этих общих элементов, продолжайте и grep каждого файла для строки, где он появляется, и отображайте только второе значение, используя awk.

Итак, в конце нам понадобился цикл bash for, sort, comm и awk несколько раз. Возможно, это не самое элегантное решение, но оно выполняет свою работу.

...