Поиск замены uniq-c для больших файлов


У меня есть большой файл (50 ГБ), и я хотел бы подсчитать количество вхождений различных строк в нем. Обычно я использую

sort bigfile | uniq -c
Но файл достаточно велик, чтобы сортировка занимала слишком много времени и памяти. Я мог бы сделать
grep -cfx 'one possible line'

Для каждой уникальной строки в файле, но это означало бы n проходов по файлу для каждой возможной строки, что (хотя и намного более удобно для памяти) занимает даже больше времени, чем оригинал.

Есть идеи?


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

3 3

3 ответа:

Использовать awk

awk '{c[$0]++} END {for (line in c) print c[line], line}' bigfile.txt
Это O(n) во времени и O (уникальные линии) в пространстве.

Вот решение, использующее jq 1.5. По сути, это то же самое, что и решение awk, как по подходу, так и по характеристикам производительности, но выводом является объект JSON, представляющий хэш. (Программа может быть тривиально модифицирована для получения выходных данных в альтернативном формате.)

Вызов:

$ jq -nR 'reduce inputs as $line ({}; .[$line] += 1)' bigfile.txt

Если bigfile.txt состоял из следующих строк:

a
a
b
a
c

Тогда выход будет:

{
  "a": 3,
  "b": 1,
  "c": 1
}
#!/bin/bash
# port this logic to awk or ksh93 to make it fast

declare -A counts=( )
while IFS= read -r line; do
  counts[$line]=$(( counts[$line] + 1 )) # increment counter
done

# print results
for key in "${!counts[@]}"; do
  count=${counts[$key]}
  echo "Found $count instances of $key"
done