2015-09-02 6 views
3

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

sort bigfile | uniq -c 

но файл достаточно велик, что сортировка требует непомерно много времени и памяти. Я мог бы сделать

grep -cfx 'one possible line' 

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

Любые идеи?


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

+0

Хеш с awk? – Cyrus

+0

Возможно, это вырожденный случай http://stackoverflow.com/questions/3502177/how-to-count-number-of-unique-values-of-a-field-in-a-tab-delimited-text- файл; ответ http://stackoverflow.com/a/22250460/14122 в значительной степени соответствует тому, что у нас уже есть, только выбирая столбец, а не используя всю строку. –

ответ

7

Применение awk

awk '{c[$0]++} END {for (line in c) print c[line], line}' bigfile.txt 

Это О (п) во время, и вывод (уникальные линии) в пространстве.

+1

Возможно, это заполняет запрос «port this logic to awk» в моей версии bash. :) –

+0

bigfile.txt может быть аргументом команды awk, не требуется перенаправление ввода. –

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 
+0

Как поможет 'grep', он будет соответствовать всем строкам? – Barmar

+0

@Barmar, он соответствует только линиям в известном наборе. Когда я прочитал вопрос, они чередуются в других строках, о которых OP не заботится. –

+0

Ahh. При более близком рассмотрении я вижу, что это не так. –

2

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

Призывание:

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

Если bigfile.t состояла из этих линий:

a 
a 
b 
a 
c 

, то выход будет :

{ 
    "a": 3, 
    "b": 1, 
    "c": 1 
}