Columns
將幾列(不同長度)轉置為行
有人問了一個與我類似的問題,涉及將多列轉換為行。但是,我正在處理的特定列格式略有不同,因為我的文件包含不同數量的列,這些列有時會重複。
例如:
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
鍵的最後一步。