여러 열(길이가 다름)을 행으로 바꿉니다.

여러 열(길이가 다름)을 행으로 바꿉니다.

누군가 여러 열을 행으로 변환하는 것과 관련하여 나와 비슷한 질문을 했습니다. 그러나 제가 작업 중인 특정 열의 형식은 약간 다릅니다. 내 파일에 다음이 포함되어 있기 때문입니다.바꾸다때로는 중복된 열 번호가 있는 경우가 있습니다.

예를 들어:

100  
1  
2
3  

200  300  
1    1  
2    2
3    3

100  
1  
2  
3

400  500  600  700  800  900  
1    1    1    1    1    1
2    2    2    2    2    2
3    3    3    3    3    3

100 400 700   
1   1   1
2   2   2
3   3   3

이 열을 다음과 같은 행으로 바꾸고 싶습니다.

100 1 2 3
200 1 2 3
300 1 2 3
100 1 2 3
400 1 2 3
500 1 2 3
600 1 2 3
700 1 2 3
800 1 2 3
900 1 2 3
100 1 2 3
400 1 2 3
700 1 2 3 

그런 다음 다음과 같이 첫 번째 열의 값을 기준으로 행을 정렬합니다.

100 1 2 3
100 1 2 3
100 1 2 3    
200 1 2 3
300 1 2 3
400 1 2 3
400 1 2 3    
500 1 2 3
600 1 2 3
700 1 2 3
700 1 2 3    
800 1 2 3
900 1 2 3 

그리고 다음과 같이 중복 행의 값을 합산합니다.

100 3 6 9    
200 1 2 3
300 1 2 3
400 2 4 6
500 1 2 3
600 1 2 3
700 2 4 6   
800 1 2 3
900 1 2 3 

100행, 400행, 700행에 중복이 있으므로 해당 열 값이 합산된 것을 알 수 있습니다.

어떤 통찰력이나 제안이라도 대단히 감사하겠습니다.

답변1

나는 이를 위해 Perl의 단락 모드를 사용합니다:

#!/usr/bin/env perl

use strict;
use warnings;

my %final_lines;        # Data structure to hold the modified lines
my $filename = shift // die "No input file given!\n";
open my $IN,'<',$filename or die "Failed to open $filename for input: $!\n";

PARAGRAPH: {
    local $/="";        # Paragraph mode
    while(<$IN>){       # Read a new "paragraph"
        my @lines  = split /\n/;
        my @fields = split /\s+/,(shift @lines);
        my $line_number =0;
        for my $line (@lines){
            my @data = split /\s+/,$line;
            map { 
                  $final_lines{$fields[$_]}->[$line_number] += $data[$_]
            } (0..$#data);
            $line_number++;
        }
    }
}

for my $key (sort { $a <=> $b } keys %final_lines){
    local $,=' ';
    print STDOUT $key,@{$final_lines{$key}};
    print STDOUT "\n";
}

다음과 같이 사용하세요:

$ /path/to/script input_file > output_file

이 코드는 테스트되었으며 정상적으로 작동합니다. @cjm이 주석에서 지적했듯이 입력 파일이 큰 경우 시간이 걸릴 수 있습니다. 시간이 가장 걸릴 가능성이 가장 높은 단계가 마지막 sort열쇠입니다.

관련 정보