Columns

將幾列(不同長度)轉置為行

  • November 22, 2013

有人問了一個與我類似的問題,涉及將多列轉換為行。但是,我正在處理的特定列格式略有不同,因為我的文件包含不同數量​​的列,這些列有時會重複。

例如:

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 行有重複項,它們的列值已被求和。

非常感謝任何見解或建議。

我會為此使用 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鍵的最後一步。

引用自:https://unix.stackexchange.com/questions/101995