열 1을 기준으로 동일한 파일의 여러 줄을 병합합니다.

열 1을 기준으로 동일한 파일의 여러 줄을 병합합니다.

저는 아직 프로그래밍을 배우는 중이고 많은 것을 시도했지만 형식을 올바르게 지정할 수 없습니다. 나는탭으로 구분됨파일에는 17개의 열과 많은(약 50,000개) 행이 있습니다. 파일은 첫 번째 열을 기준으로 정렬됩니다. 동일한 첫 번째 열(A)이 있는 행을 병합하고 싶지만 다른 16개 열은 모두 다르며 모든 정보를 한 행, 바람직하게는 동일한 열에 유지하고 싶습니다.세미콜론 ;그들 사이의 구분자로. 출력 파일에서 탭 문자를 구분 기호로 유지하고 싶습니다. 답변해 주셔서 대단히 감사합니다. 제가 어디에서 잘못되었는지 설명해 주시면 더 좋을 것 같습니다. :)

내가 지금까지 시도한 것 :

awk -F'\t' 'NF>1{a[$1] = a[$1]";"$2}END{for(i in a){print i""a[i]}}' filename.txt

perl -F',' -anle 'next if /^$/;$h{$F[0]} = $h{$F[0]}.", ".$F[1];
END{print $_,$h{$_},"\n" for sort keys %h}' filename.txt

파일 형식(나머지 15개 열은 B열과 형식이 동일함)

A     B     C    
123   fvv   ggg
123   kjf   ggg
123   ccd   att
567   abc   gst
567   abc   hgt
879   ttt   tyt

내가 원하는 출력(17개 열이 모두 필요하고, 2-16열에는 B열과 C열과 동일한 출력이 필요합니다). B의 모든 케이스는 B 아래에 있어야 하고, C의 모든 케이스는 C 아래에 있어야 하며, D의 모든 케이스는 D 아래에 있어야 합니다. 따라서 출력에는 입력과 동일한 17개의 열이 있으며, 첫 번째 열(이 특정 파일의 경우)에 많은 반복이 있으므로 이제 50,000개의 행 대신 약 20,000개의 행이 있어야 합니다.

A     B                C
123   fvv;kjf;ccd      ggg;ggg;att
567   abc;abc          gst;hgt
879   ttt              lll

답변1

awk '{
      if(NR!=1){a[$1]=$2";"a[$1]}
      else print $0}
    END{
      n = asorti(a, b);
      for (n in b) {
      print b[n],a[b[n]]
      }
    }'

답변2

펄 솔루션:

$ perl -F"\t" -anle 'if($.==1){print; next} push @{$k{$F[0]}},@F[1..$#F]; 
  END{print "$_\t" . join(";",@{$k{$_}}) for sort keys(%k)}' file 
A   B   
123 fvv;kjf;ccd
567 abc;abc
879 ttt

이는 여러 필드에 적용될 수 있습니다. 그러나 상당한 양의 콘텐츠를 메모리에 로드해야 하므로 파일이 큰 경우 문제가 될 수 있습니다.


어디서 잘못되었는지에 관해서는 실제로 무슨 일이 일어났는지 설명하지 않으면 알 수 없습니다. 하지만 제 머리로는 다음과 같은 이유로 Perl 시도가 실패했습니다.

  • 입력에 탭이 있는 경우 -F,이를 사용하여 필드 구분 기호를 쉼표로 설정합니다.
  • -l및 을(를) 사용하고 있습니다 print "foo\n". 각 인쇄 호출에 개행 문자가 추가 되었으므로 -l여러 개의 빈 줄이 생깁니다.
  • 추가를 사용하고 있으므로 $h{$F[0]}.", ".$F[1];처음 실행하고 정의되지 않은 경우 저장된 값의 시작 부분에 추가 값을 추가 $h{$F[0]}하게 됩니다 .,
  • 두 번째 필드만 보고 다른 모든 필드는 무시합니다.

awk마찬가지로 다음과 같은 이유로 귀하의 의지가 실패하게 됩니다.

  • 인쇄 중입니다 foo""bar. 이렇게 하면 각 필드 사이에 공백 없이 출력이 연결됩니다. 탭으로 구분된 출력을 원 print foo,bar하고 원합니다 OFS="\t".
  • 두 번째 필드만 보고 다른 모든 필드는 무시합니다.

답변3

죄송하지만 문제는 이렇습니다.

awk 'BEGIN{FS="\t"} {for(i=2; i<=NF; i++) { if (!a[$1]) a[$1]=$1FS$i ;else a[$1]=a[$1]";"$i};if ($1 != old) b[j++] = a[old];old=$1 } END{for (i=0; i<j; i++) print b[i] }' 1

123 fvv ;kjf;ccd
567 abc;abc
879 ttt

답변4

awk '
    function p(n,A){
        s = n
        for(i=2;i<=NF;i++){
            s = s "\t" A[i]
            A[i] = $i
        }
        if(n)
            print s
    }
    NR==1{
        print
        next
    }
    $1==n{
        for(i=2;i<=NR;i++)
            A[i] = A[i] ";" $i
        next
    }
    {
        p(n,A)
        n = $1
    }
    END{
        p(n,A)
    }
    ' file

관련 정보