Как я могу сравнить два текстовых файла, который имеет несколько полей в Unix - PullRequest
1 голос
/ 06 июля 2010

у меня есть два текстовых файла

  • файл 1

    number,name,account id,vv,sfee,dac acc,TDID
    7000,john,2,0,0,1,6
    7001,elen,2,0,0,1,7
    7002,sami,2,0,0,1,6
    7003,mike,1,0,0,2,1
    8001,nike,1,2,4,1,8
    8002,paul,2,0,0,2,7 
    
  • файл 2

    number,account id,dac acc,TDID
    7000,2,1,6
    7001,2,1,7
    7002,2,1,6
    7003,1,2,1
    

Я хочу сравнить эти два текстовых файла. если в файле 1 есть четыре столбца файла 2 и равно, значит, я хочу вывод, как это

7000,john,2,0,0,1,6
7001,elen,2,0,0,1,7
7002,sami,2,0,0,1,6
7003,mike,1,0,0,2,1

nawk -F"," 'NR==FNR {a[$1];next} ($1 in a)' file2.txt file1.txt .. это хорошо работает для сравнения двух столбцов в двух файлах. Я хочу сравнить несколько столбцов. У кого-нибудь есть предложение?


РЕДАКТИРОВАТЬ: Из комментариев ОП:

nawk -F"," 'NR==FNR {a[$1];next} ($1 in a)' file2.txt file1.txt

.. это хорошо работает для сравнения двух столбцов в двух файлах. Я хочу сравнить несколько столбцов. у вас есть предложения?

Ответы [ 7 ]

3 голосов
/ 07 июля 2010

Этот awk однострочный работает для нескольких столбцов на несортированных файлах:

awk -F, 'NR==FNR{a[$1,$2,$3,$4]++;next} (a[$1,$3,$6,$7])' file1.txt file2.txt

Для того, чтобы это работало, обязательно, чтобы первым файлом, использованным для ввода (file1.txt в моем примере), был файл, имеющий только 4 поля, например:

file1.txt

7000,2,1,6
7001,2,1,7
7002,2,1,6
7003,1,2,1

file2.txt

7000,john,2,0,0,1,6
7000,john,2,0,0,1,7
7000,john,2,0,0,1,8
7000,john,2,0,0,1,9
7001,elen,2,0,0,1,7
7002,sami,2,0,0,1,6
7003,mike,1,0,0,2,1
7003,mike,1,0,0,2,2
7003,mike,1,0,0,2,3
7003,mike,1,0,0,2,4
8001,nike,1,2,4,1,8
8002,paul,2,0,0,2,7

выход

$ awk -F, 'NR==FNR{a[$1,$2,$3,$4]++;next} (a[$1,$3,$6,$7])' file1.txt file2.txt
7000,john,2,0,0,1,6
7001,elen,2,0,0,1,7
7002,sami,2,0,0,1,6
7003,mike,1,0,0,2,1

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

awk -F, 'NR==FNR{a[$1,$2,$3,$4];next} ($1SUBSEP$3SUBSEP$6SUBSEP$7 in a)' file1.txt file2.txt
1 голос
/ 06 июля 2010

Это не элегантный однострочный текст, но вы можете сделать это с помощью Perl.

#!/usr/bin/perl
open A, $ARGV[0];
while(split/,/,<A>) {
    $k{$_[0]} = [@_];
}
close A;

open B, $ARGV[1];
while(split/,/,<B>) {
    print join(',',@{$k{$_[0]}}) if
        defined($k{$_[0]}) &&
        $k{$_[0]}->[2] == $_[1] &&
        $k{$_[0]}->[5] == $_[2] &&
        $k{$_[0]}->[6] == $_[3];
}
close B;
1 голос
/ 06 июля 2010

TxtSushi выглядит так, как вы хотите. Позволяет работать с CSV-файлами с использованием SQL.

0 голосов
/ 22 декабря 2011

Статистический пакет R действительно легко обрабатывает несколько таблиц CSV. См. Введение. R или R для начинающих .

0 голосов
/ 06 июля 2010

Не очень хорошо протестировано, но это может сработать:

join -t, file1 file2 | awk -F, 'BEGIN{OFS=","} {if ($3==$8 && $6==$9 && $7==$10) print $1,$2,$3,$4,$6,$7}'

(Конечно, это предполагает, что входные файлы отсортированы).

0 голосов
/ 06 июля 2010

Это не эффективно и не красиво, однако оно выполнит работу.Это не самая эффективная реализация, поскольку она анализирует file1 несколько раз, однако она не считывает весь файл в ОЗУ, поэтому имеет некоторые преимущества по сравнению с простыми сценариями.

sed -n '2,$p' file1 | awk -F, '{print $1 "," $3 "," $6 "," $7 " " $0 }' | \
sort | join file2 - |awk '{print $2}'

Это работает следующим образом

  1. sed -n '2,$p' file1 отправляет файл1 в STDOUT без строки заголовка
  2. Первая команда awk выводит 4 «ключевых поля» из файла1 в том же формате, в котором они находятся в файле2, после чего следует пробелпо содержимому file1
  3. Команда sort гарантирует, что file1 находится в том же порядке, что и file2
  4. Команда join объединяет file2 и STDOUT только для записи записей, имеющих совпадающую запись в file2
  5. Последняя команда awk печатает только оригинальную часть file1

Чтобы это работало, вы должны убедиться, что file2 отсортирован перед запуском команды.

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

Что-то подобное сделает это для вас

mv file2 file2.orig
for i in 0 1 2 3 4 5 6 7 8 9
do
  grep "^${i}" file2.orig |sort > file2.$i
done
cat file2.[0-9] >file2
rm file2.[0-9] file2.orig

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

0 голосов
/ 06 июля 2010

Быстрый ответ: используйте cut, чтобы выделить нужные поля, и diff, чтобы сравнить результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...