Text-Formatting

將行轉換為列數據的 Linux shell 腳本

  • August 2, 2021

我想從下面的輸入文件轉換數據,轉換行 tp 列:

輸入:

Avamar Hostname                 server1.corpnet2.com
Avamar Server Version           19.1.0-38 
Node Type                       Single Node Gen4t-M2400
Gen4T ROC SN/WWN                WARNING
EMC Hardware Health             PASSED
Avamar Hostname                 server2.CORPNET2.COM
Avamar Server Version           19.1.0-38
Node Type                       Single Node Gen4t-M1200
Gen4T ROC SN/WWN                WARNING
EMC Hardware Health             PASSED

所需輸出:

Avamar Hostname        Avamar Server Version   Node Type               Gen4T ROC SN/WWN EMC Hardware Health
server1.corpnet2.com   19.1.0-38               Single Node Gen4t-M2400 WARNING          PASSED
server2.CORPNET2.COM   19.1.0-38               Single Node Gen4t-M1200 WARNING          PASSED
#!/usr/bin/perl
use strict;

my @keynames = (
 'Avamar Hostname', 'Avamar Server Version','Node Type',
 'Gen4T ROC SN/WWN', 'EMC Hardware Health',
);

# Make a hash where the keys are the key names, and the values
# are the index number of the key. This will make sure each
# field of every record is stored and printed in the right order.
my %keys;
foreach (0 .. $#keynames) { $keys{$keynames[$_]} = $_; };

# String field lengths are hard-coded after examining the sample data.
#
# These could be auto-calculated at the cost of having two
# passes through the data, and keeping the max length of
# each field in a hash. The hash should be initialised
# (in the foreach loop above) with the lengths of the headers
# so they're at least that wide.
my $fmt = "%-20s  %-21s  %-23s  %-16s  %-19s\n";

my @record;

printf $fmt, @keynames;

while(<>) {
 chomp;
 # split the input line on two-or-more spaces or a tab.
 # I'm not sure if the input is tab or space separated,
 # this will work with either.
 my ($key,$val) = split /  +|\t/;

 if ($. > 1 && (eof || $key eq $keynames[0])) {
   printf $fmt, @record;
   @record=();
 };

 $record[$keys{$key}] = $val;
}

樣本輸出:

$ ./row-to-col.pl input.txt  
Avamar Hostname       Avamar Server Version  Node Type                Gen4T ROC SN/WWN  EMC Hardware Health
server1.corpnet2.com  19.1.0-38              Single Node Gen4t-M2400  WARNING           PASSED
server2.CORPNET2.COM  19.1.0-38              Single Node Gen4t-M1200  WARNING           PASSED

注意:如果每條記錄之間至少有一個空行,這將更容易處理。然後可以在段落模式下對其進行解析。如果您可以修改生成輸入數據的任何內容來執行此操作,那麼我建議您這樣做。當然,如果你能做到這一點,你也可以修改它來生成這種表格格式。

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