Найти совпадения для 5-го столбца в файлах с разделителями каналов

Найти совпадения для 5-го столбца в файлах с разделителями каналов
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Мне нужно найти совпадающие записи в Файле 1 и Файле 2 в столбце 5. Поэтому из вышесказанного мне нужно вернуть в выводе:

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Большое спасибо,

решение1

Метод №1: grep и awk

Для этого можно использовать этот фрагмент:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Подробности

Бит, который использует, awkанализирует первый файл, file1вытаскивая все 5-е столбцы. Затем эти значения используются как список для grep, который выведет все строки во 2-м файле, содержащие совпадение.

Предостережения относительно этого метода

Этот метод будет соответствовать любому вхождению 5-го столбца file1из file2.

Метод №2: Просто awk

Другой подход, который использовался на сайте в прошлом, заключается в использовании awkвозможности FNR. Это то, где awkбудет выполнена итерация по 2 файлам, прохождение второго файла построчно для каждой строки в первом.

Такой подход сделает это. Поместите следующее в файл cmds.awk:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

Затем вы можете запустить это следующим образом:

$ awk -F '|' -f cmds.awk file1 file2

ПРИМЕЧАНИЕ:Вместо этого можно было бы использовать такой awkшаблон:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

Пример

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Предостережения относительно этого метода

Этот подход может обрабатывать только один экземпляр каждого адреса электронной почты из file1. Так что если есть 2 строки, которые имеют одинаковое значение для 5-го столбца, это не сможет различить их. Это кажется приемлемым, учитывая ваши требования в OP.

Присоединиться и отсортировать

Вы также можете сделать это с помощью joinи sort.

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

Это будет использовать разделитель |и объединять отсортированные файлы в 5-м столбце. Этот подход печатает совпадения из обоих file1и file2, поэтому мы используем sed, чтобы отсечь 2-е совпадение с конца.

Пример

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578

решение2

Я бы сделал все это на Perl:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -aактивирует автоматическое разбиение полей на массив @F.
  • -F'\|'устанавливает разделитель полей -aдля |.
  • Для каждой обработанной строки сохраните 5-е поле (индексы массива начинаются с 0в Perl) как хэш-ключ ( $k{$F[4]}++и увеличьте его значение на единицу. При втором появлении поля это значение будет равно 2.
  • Скрипт обработает каждую строку обоих файлов ( file1предыдущую file2) и выведет строку, если пятое поле уже встречалось ранее, т.е. если $k{$F[4]}оно больше единицы.

Это предполагает, что пятый столбец не повторяется в пределахтакой жефайл. Если это не так и некоторые столбцы могут дублироваться в одном файле, используйте это:

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 

решение3

Если размеры файлов сопоставимы, оптимальным решением будетsortоба файла по интересующему вас столбцу, а затемjoinих по этому столбцу. Если размеры файлов Nи Mтогда асимптотическое время выполнения O(N*log(N)+M*log(M)).

Если один из файлов намного меньше другого, то O(N*M)решение в других ответах лучше.

Связанный контент