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

File 1: Connect|20130320000023|UTC|PPP|test3@test3.co.uk|test1@test1.co.uk|0BCBE578| File 2: Connect|20130320000023|UTC|PPP|test1@test1.co.uk|test1@test1.co.uk|0BCBE578| Connect|20130320000025|UTC|PPP|test2@test2.co.uk|test1@test1.co.uk|0BCBE578| Connect|20130320000025|UTC|PPP|test3@test3.co.uk|test1@test1.co.uk|0BCBE578| 

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

 Connect|20130320000025|UTC|PPP|test3@test3.co.uk|test1@test1.co.uk|0BCBE578| 

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

Метод № 1: grep & awk

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

 $ grep -f <(awk -F '|' '{print $5}' file1) file2 Connect|20130320000025|UTC|PPP|test3@test3.co.uk|test1@test1.co.uk|0BCBE578| 

Детали

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

Предостережения с этим методом

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

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

Другой подход, который использовался на прошлом в прошлом, заключается в использовании средства FNR awk . Здесь 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|test3@test3.co.uk|test1@test1.co.uk|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 для прерывания второго совпадения.

пример

 $ join -t '|' -j 5 <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//' test3@test3.co.uk|Connect|20130320000025|UTC|PPP|test1@test1.co.uk|0BCBE578 

Я бы сделал все в Perl:

 $ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2 Connect|20130320000025|UTC|PPP|test3@test3.co.uk|test1@test1.co.uk|0BCBE578| 
  • -a активирует автоматическое разделение поля в массиве @F .
  • -F'\|' устанавливает разделитель полей для -a в | ,
  • Для каждой обрабатываемой строки сохраните пятое поле (индексы массива начинаются с 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 в 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 в 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 

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

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