2012-05-05 3 views
0

Как подсчитать экземпляры строк в файле с разделителями разделов (tsv)?Как подсчитать экземпляры строки в файле с разделителями вкладок?

Файл TSV имеет сотни миллионов строк, каждая из которых имеет форму

foobar1 1 xxx yyy 
foobar1 2 xxx yyy 
foobar2 2 xxx yyy 
foobar2 3 xxx yyy 
foobar1 3 xxx zzz 

. Как подсчитать экземпляры каждого уникального целого во всем втором столбце в файле и в идеале добавить счет в качестве пятого значения в каждой строке?

foobar1 1 xxx yyy 1 
foobar1 2 xxx yyy 2 
foobar2 2 xxx yyy 2 
foobar2 3 xxx yyy 2 
foobar1 3 xxx zzz 2 

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

+0

пожалуйста вставить некоторые образцы данных, и ваш ожидает выход. – Kent

ответ

1

Я не совсем понимаю, что вы хотите сделать. Вы хотите добавить 0/1 в зависимости от значения второго столбца в качестве пятого столбца или вы хотите получить распределение значений во втором столбце, всего для всего файла?

В первом случае используйте что-то наподобие awk -F'\t' '{ if($2 == valueToCheck) { c = 1 } else { c = 0 }; print $0 "\t" c }' < file.

Во втором случае используйте что-то вроде awk -F'\t' '{ h[$2] += 1 } END { for(val in h) print val ": " h[val] }' < file.

+0

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

+0

Будет ли применимость использования массива 'h [$ 2]' зависит от того, насколько велика наибольшее целое число? Без проверки, но возможно, что целое число во втором столбце может быть больше, чем самый большой номер машины. – qazwsx

+0

Вы должны хотя бы получить сообщение об ошибке, если это так. –

0

Одно решение с использованием perl, считая, что значения второго столбца отсортированы, я имею в виду, когда найденное значение 2, все строки с одинаковым значением будут последовательными. Скрипт хранит строки до тех пор, пока не найдет другое значение во второй колонке, получить счетчик, распечатать их и освобождает память, поэтому не должен создавать проблемы независимо от того, насколько большой входной файл:

Содержание script.pl:

use warnings; 
use strict; 

my (%lines, $count); 

while (<>) { 

    ## Remove last '\n'. 
    chomp; 

    ## Split line in spaces. 
    my @f = split; 

    ## Assume as malformed line if it hasn't four fields and omit it. 
    next unless @f == 4; 

    ## Save lines in a hash until found a different value in second column. 
    ## First line is special, because hash will always be empty. 
    ## In last line avoid reading next one, otherwise I would lose lines 
    ## saved in the hash. 
    ## The hash will ony have one key at same time. 
    if (exists $lines{ $f[1] } or $. == 1) { 
     push @{ $lines{ $f[1] } }, $_; 
     ++$count; 
     next if ! eof; 
    } 

    ## At this point, the second field of the file has changed (or is last line), so 
    ## I will print previous lines saved in the hash, remove then and begin saving 
    ## lines with new value. 

    ## The value of the second column will be the key of the hash, get it now. 
    my ($key) = keys %lines; 

    ## Read each line of the hash and print it appending the repeated lines as 
    ## last field. 
    while (@{ $lines{ $key } }) { 
     printf qq[%s\t%d\n], shift @{ $lines{ $key } }, $count; 
    } 

    ## Clear hash. 
    %lines =(); 

    ## Add current line to hash, initialize counter and repeat all process 
    ## until end of file. 
    push @{ $lines{ $f[1] } }, $_; 
    $count = 1; 
} 

Содержание infile:

foobar1 1 xxx yyy 
foobar1 2 xxx yyy 
foobar2 2 xxx yyy 
foobar2 3 xxx yyy 
foobar1 3 xxx zzz 

Выполнить это нравится:

perl script.pl infile 

С следующим выводом:

foobar1 1 xxx yyy 1 
foobar1 2 xxx yyy 2 
foobar2 2 xxx yyy 2 
foobar2 3 xxx yyy 2 
foobar1 3 xxx zzz 2 

 Смежные вопросы

  • Нет связанных вопросов^_^