2012-05-05 2 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

PLS는 일부 샘플 데이터를 붙여 여러분의 기대 출력. – 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

2 값을 찾으면 동일한 값을 가진 모든 줄이 연속적으로 표시된다는 것을 의미하는 두 번째 열의 값을 정렬한다고 가정 할 때 하나의 해결책은 perl입니다. 이 두 번째 열에서 다른 값을 찾을 때까지 스크립트가 선을 유지 카운트를 얻을, 그들을 인쇄 메모리를 해제, 그래서 관계없이 입력 파일이 얼마나 큰의 문제가 발생하지 않아야

내용 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 
01 다음과 같은 출력으로 23,516,

:

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 
관련 문제