Даже после `sort`,` uniq` все еще повторяет некоторые значения - PullRequest
5 голосов
/ 13 января 2020

Справочный файл: http://snap.stanford.edu/data/wiki-Vote.txt.gz

(Это архив на ленте, содержащий файл с именем Wiki-Vote.txt)

Первый несколько строк в файле, который содержит следующее: head -n 10 Wiki-Vote.txt

# Directed graph (each unordered pair of nodes is saved once): Wiki-Vote.txt 
# Wikipedia voting on promotion to administratorship (till January 2008). 
# Directed edge A->B means user A voted on B becoming Wikipedia administrator.
# Nodes: 7115 Edges: 103689
# FromNodeId    ToNodeId
     30          1412
     30          3352
     30          5254
     30          5543
     30          7478
     3            28

Я хочу найти количество узлов в графе (хотя оно уже указано в строке 3). Я выполнил следующую команду:

awk '!/^#/ { print $1; print $2; }' Wiki-Vote.txt | sort | uniq | wc -l

Объяснение:

  • /^#/ соответствует всем строкам, начинающимся с #. И !/^#/ соответствует, что не соответствует.

  • awk '!/^#/ { print $1; print $2; }' Wiki-Vote.txt печатает первый и второй столбец всех этих совпадающих строк в новых строках.

  • | sort передает выходные данные для их сортировки.

  • | uniq должен отображать все эти уникальные значения, , но не .

  • | wc -l подсчитывает предыдущие строки, и это неверно.

Результат приведенной выше команды 8491, что не 7115 (как указано в строке 3). Я не знаю, почему uniq повторяет значения. Я могу сказать, что поскольку awk '!/^#/ { print $1; print $2; }' Wiki-Vote.txt | sort -i | uniq | tail возвращает,

992
993
993
994
994
995
996
998
999
999

, который содержит повторяющиеся значения. Кто-нибудь, пожалуйста, запустите код и скажите, что я не единственный, кто получает неправильный ответ, и, пожалуйста, помогите мне понять, почему я получаю то, что получаю.

1 Ответ

9 голосов
/ 13 января 2020

В файле есть окончания строки DOS - каждая строка заканчивается символом \r CR.

Вы можете проверить вывод tail, например, с помощью hexdump -C, строки, начинающиеся с #, добавляются с помощью me:

$ awk '!/^#/ { print $1; print $2; }' ./wiki-Vote.txt | sort | uniq | tail | hexdump -C
00000000  39 39 32 0a 39 39 33 0a  39 39 33 0d 0a 39 39 34  |992.993.993..994|
#                                           ^^ HERE
00000010  0a 39 39 34 0d 0a 39 39  35 0d 0a 39 39 36 0a 39  |.994..995..996.9|
#                     ^^              ^^ 
00000020  39 38 0a 39 39 39 0a 39  39 39 0d 0a              |98.999.999..|
#                                        ^^
0000002c

Поскольку uniq видит уникальные строки, одна с CR, а другая нет, они не удаляются. Удалите символ CR перед конвейером. Обратите внимание, что sort | uniq лучше, чем sort -u.

$ awk '!/^#/ { print $1; print $2; }' ./wiki-Vote.txt | tr -d '\r' | sort -u | wc -l
7115
...