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|
Большое спасибо,
Вы можете использовать этот фрагмент для этого:
$ 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
.
Другой подход, который использовался на прошлом в прошлом, заключается в использовании средства 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)
в других ответах лучше.