unique - фильтрация дубликатов силами легендарного взломщика
искал способ убирать дубликаты строчек из файла.
привычный спобос
cat file_with_dupe | sort | uniq > distinct
не подходит, т.к. сбивает оригинальную сортировку.
помощь получил, с неожиданной стороны: легендарый взломщик паролей John The Ripper имеет в себе нужный мне функционал.
содержит утилитку unique, которая хоть и является симлинком на john, но вызывая её - получаю именно тот сортировщик:
cat file_with_dupe | ./unique distinct
к сожалению работает только в таком синтаксисе единственный параметр OUTPUT_FILE : принимает поток с stdin и отдает фильтрованный результат в файл OUTPUT_FILE
(1 vote)
- 1972 просмотра
Страница для печати


если подфиксить в исходниках john the ripper
в файле unique.c, в функции static void unique_init(char *name)
изменить проверку
на
тогда собрав john, можно в качесве параметра давать существующие файлы, пайпы, девайс /dev/stdout например.
однако потестив:
time perl -lne'$x{$_}++||print' < example.txt 1>&- real 0m33.592s user 0m32.768s sys 0m0.465s time awk '{ if (!x[$0]) { print $0; x[$0]=1 } }' < example.txt 1>&- real 0m18.620s user 0m17.805s sys 0m0.367s time unique /dev/stdout < example.txt 1>&- real 0m33.331s user 0m30.506s sys 0m0.732sмне стало обидно за Кернигана и Риччи.
Спасибо, а то я вечно изобретал что-то вроде cat -n | sort -u -k2 | sort -n
и ломал голову, как покрасивее отрезать потом номера.
Интересно, насколько надёжны оба способа -- с awk и unique?
>искал способ убирать дубликаты строчек из файла.
>привычный спобос
>cat file_with_dupe | sort | uniq > distinct
а почему просто не
at file_with_dupe | sort -u > distinct
?
ты бы попробовал? Ж:-)
sort делает "уникальными" только строки идущие рядом. тоесть надо сначала перед sort -u отсортировать эти строки
cat file_with_dupe |awk '!t[$0] { t[$0]=1; print }'
помоему не хорошо призывая учить awk давать код, которым только что новичков и отпугивать. ведь можно было бы и по понятному типа:
# используем "массивы" awk, аналог хешей в perl. # t это массив в котором как индекс используется текущая строка, # если в элементе этого массива что то есть, то эта строка уже была $ printf "1\n2\n1\n" |awk '{ if (!t[$0]) { t[$0]=1; print }}'PS
если говорить не о новичках, то так короче Ж:-)
$ printf "1\n2\n1\n" |awk '!t[$0]++{print}'Учитывая то, что print - это действие awk по дефолту, то еще короче :)
2 darkk:
А здесь нет проверки по модулю 2 :) Проблема могла бы быть только с переполнением целых чисел, а у вещественной арифметики все ок.
о. век живи, век rtfm Ж:-)
а этот приемчик с ++ я где то в перловых однострочниках подсмотрел
и читайте, к примеру, http://www.catonmat.net/tag/awk
А мне что-то влом писать то, что уже неоднократно разжёвано другими :)
Короче. Но не аккуратно:
$ echo | awk ' ((2^53 + 1) % 2 == 0) { print "gotcha";}'
gotcha
Отправить комментарий