Я бы использовалawk
:
awk 'NR==FNR{a[$0]++;next}a[$1]' file1 file2
где ваши идентификаторы находятся в файле1, а остальные — в файле2. Выход:
1 96 283 4
3 57 294 0
3 24 284 0
8 19 239 78
8 18 289 90
awk '
!B {a[$1]++}
B && a[$1] > 1
' B=0 file B=1 file
Получите первое поле (= ID )и отсортируйте его, а затем уникализируйте идентификаторы и сохраните только дубликаты. Передайте их xargs и создайте регулярное выражение egrep ERE из каждого такого идентификатора.
< file \
cut -d" " -f1 \
| sort | uniq -d \
| xargs -I{} echo ^{}\\s \
| grep -Ef - file \
;
Используя perl
, мы глотаем опцию файла -0777
и запускаем регулярное выражение через запись, и если в каждой строке, начинающейся ^
, мы можем увидеть первое поле (= ID )ниже или идентификатор уже встречался ранее, напечатайте текущую строку
perl -0777ne '
() = m/(?msx)
^
(?<line>
(?<ID> A\w+)
\h.*?\n
)
(?=
(?:.*?\n)?
(?<lukahead> \g{ID}|$)
)
(?{ my %seen;
my($id_visible_ahead, $id_already_seen) =
map { $_ > 0 }
length($+{lukahead}), $seen{$+{ID}};
print($+{line}),$seen{$+{ID}}++
if $id_visible_ahead || $id_already_seen;
})
/g;
' file
Выход:
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
Во-первых, будут возвращены все повторяющиеся идентификаторы, которые вы хотели бы сохранить.:
$ awk '{ print $1 }' <file | sort | uniq -d
A2SGWS7CUGU8GB
Он делает это, извлекая первое поле с разделителями -пробелами, идентификатор, используя awk
. Затем он сортируется, и uniq -d
используется для вывода только дублирующихся идентификаторов.
Затем мы можем использовать эти (единичные, в данном случае )идентификаторы, для извлечения соответствующих строк из исходного файла, который необходимо сначала отсортировать, используяjoin
:
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file )
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
Если ваша оболочка не поддерживает подстановку процессов с использованием <(...)
, вы можете сделать это в два -шага, используя временный файл:
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
Используя только awk
, это можно сделать следующим образом:
$ awk 'NR == FNR { count[$1]++; next } count[$1] > 1' file file
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
Обратите внимание, что файл дважды упоминается в командной строке, так как он дважды считывается кодом awk
.
В первый раз ассоциативный массив count
заполняется количеством просмотров каждого ID, а во второй раз выводится каждая строка, которая имеет ID, который был просмотрен более одного раза.
Разница между двумя описанными выше подходами заключается в том, что команда awk
, представленная последней, сохраняет порядок исходных данных, но потребляет память, пропорциональную количеству уникальных идентификаторов. Первый подход будет генерировать отсортированные результаты и может быть более подходящим для очень больших данных.
Для сохранения строки заголовка команды нужно немного изменить:
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file ) | cat <(head -1 file) -
или
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted > file.noheader
$ head -1 file | cat - file.noheader
или
$ awk 'NR == 1 ; NR == FNR { count[$1]++; next } count[$1] > 1' file file