У меня есть файл, содержащий два столбца и 10 миллионов строк. Первый столбец содержит много повторяющихся значений, но в столбце 2 есть отдельное значение. Я хочу удалить повторяющиеся строки и оставить только одну, используя awk
. Примечание: файл отсортирован по значениям в столбце 1. Например:
1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.
Ожидаемый результат
1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.
решение1
Несколько способов:
awk
awk '!a[$1]++' file
Вот очень сжатый способ записи этого:
awk '{if(! a[$1]){print; a[$1]++}}' file
Итак, если текущего первого поля (
$1
) нет вa
массиве, вывести строку и добавить 1-е поле кa
. В следующий раз, когда мы увидим это поле, оно будет в массиве и поэтому не будет выведено.Перл
perl -ane '$k{$F[0]}++ or print' file
или
perl -ane 'print if !$k{$F[0]}++' file
Это в основном то же самое, что и
awk
один.-n
заставляет perl читать входной файл построчно и применять скрипт, предоставленный к-e
каждой строке.-a
автоматически разобьет каждую строку по пробелам и сохранит полученные поля в@F
массиве. Наконец, первое поле добавляется в%k
хэш, и если его там еще нет, строка выводится. То же самое можно записать какperl -e 'while(<>){ @F=split(/\s+/); print unless defined($k{$F[0]}); $k{$F[0]}++; }' file
Coreutils
rev file | uniq -f 1 | rev
Этот метод работает, сначала переворачивая строки так,
file
что если строка 12 345, то теперь она будет 543 21. Затем мы используем ,uniq -f 1
чтобы игнорировать первое поле, то есть столбец, в котором находится 543. Есть поля внутриfile
. Использованиеuniq
здесь имеет эффект фильтрации любых дубликатов строк, оставляя только по одной из каждой. Наконец, мы возвращаем строки в их исходный порядок с помощью еще одного переворота.Сортировка GNU (какпредложенныйот @StéphaneChazelas)
sort -buk1,1
Флаг
-b
игнорирует начальные пробелы и-u
означает печать только уникальных полей. Умный момент —-k1,1
.-k
Флаг задает поле для сортировки. Он принимает общий формат,-k POS1[,POS2]
который означает просмотр только полейPOS1
через POS2 при сортировке. Таким образом,-k1,1
означает просмотр только 1-го поля. В зависимости от ваших данных вы можете также добавить одну из этих опций:-g, --general-numeric-sort compare according to general numerical value -n, --numeric-sort compare according to string numerical value
решение2
Если длина первого столбца всегда составляет 5 символов, вы можете просто использовать uniq
:
uniq -w 5 file
Если нет, используйте awk
:
awk '$1!=a{print $0; a=$1}' file
Первый вариант определенно будет быстрее с большим файлом.