Сравните два столбца разных файлов и добавьте новый столбец, если он совпадает

#shell #unix #awk

#оболочка #unix #awk

Вопрос:

Я хотел бы сравнить первые два столбца из двух файлов, если они совпадают, нужно напечатать yes, иначе no.

input.txt

 123,apple,type1
123,apple,type2
456,orange,type1
6567,kiwi,type2
333,banana,type1
123,apple,type2
  

qualified.txt

 123,apple,type4
6567,kiwi,type2
  

output.txt

 123,apple,type1,yes
123,apple,type2,yes
456,orange,type1,no
6567,kiwi,type2,yes
333,banana,type1,no
123,apple,type2,yes
  

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

Теперь input.txt имеет дубликат (1-й столбец), поэтому приведенный ниже метод не работает, кроме того, размер файла был огромным.

Можем ли мы получить output.txt в awk одном лайнере?

 comm -2 -3 input.txt qualified.txt
  

Комментарии:

1. Почему первые 2 столбца? Похоже, что первые 2 всегда сопряжены, так почему бы просто не сравнить 1 из них? Если они не всегда сопряжены (например, у вас может быть 123,apple и 9631,apple ), включите это в свой пример.

Ответ №1:

 $ awk -F, 'NR==FNR {a[$1 FS $2];next} {print $0 FS (($1 FS $2) in a?"yes":"no")}' qual input
123,apple,type1,yes
123,apple,type2,yes
456,orange,type1,no
6567,kiwi,type2,yes
333,banana,type1,no
123,apple,type2,yes
  

Объяснено:

 NR==FNR {                    # for the first file
    a[$1 FS $2];next         # aknowledge the existance of qualified 1st and 2nd field pairs
} 
{
    print $0 FS ($1 FS $2 in a?"yes":"no")        # output input row and "yes" or "no"
}                                                 # depending on whether key found in array a
  

Нет необходимости переопределять OFS , поскольку $0 он не изменяется и не перестраивается.

Ответ №2:

Вы можете использовать awk логику для этого, как показано ниже. Не уверен, почему вы упоминаете однострочную команду awk.

 awk -v FS="," -v OFS="," 'FNR==NR{map[$1]=$2;next} {if($1 in map == 0) {$0=$0FS"no"} else {$0=$0FS"yes"}}1' qualified.txt input.txt

123,apple,type1,yes
123,apple,type2,yes
456,orange,type1,no
6567,kiwi,type2,yes
333,banana,type1,no
123,apple,type2,yes
  

Логика

  • Команда FNR==NR анализирует первый файл qualified.txt и сохраняет записи в столбце 1 и 2 в первом файле, причем первый столбец является индексом.
  • Затем для каждой строки во 2-м файле {if($1 in map == 0) {$0=$0FS"no"} else {$0=$0FS"yes"}}1 запись в столбце 1 не соответствует массиву, добавьте no строку и yes в противном случае.
  • -v FS="," -v OFS="," предназначены для установки разделителей полей ввода и вывода

Комментарии:

1. Отсутствие пробела после -v делает ваш скрипт совершенно излишне специфичным для gawk. Имя массива seen идиоматически используется для представления набора, а не сопоставления. Используйте map или аналогичный вместо этого для ясности, если вы создаете карту, но я не вижу, чтобы вы на самом деле ссылались на нее как на карту, просто заполняя ее как таковую, поэтому idk…

2. @EdMorton: Спасибо за исправление, жаль, что я не знал об этом раньше 🙂

Ответ №3:

Похоже, все, что вам нужно, это:

 awk 'BEGIN{FS=OFS=","} NR==FNR{a[$1];next} {print $0, ($1 in a ? "yes" : "no")}' qualified.txt output.txt