2

我有如下输入格式,我想为这些数据创建一个表格格式。

CELL    = "abc"
        "model"         "abc"
        "description"   "qwerty+keypad with slide"
**tech**
        size    (big \$l \$w m)
        termOrder         (x y z)
        namePrefix        "S"
        prop       (nil \$l l \$w w)
    **spec**
        term      (nil C \:1 B \:2 E \:3)
        termOrder         (x y z)
***********************************************************
 CELL    = "efg"
        "model"        "efg"
        "description"  "touchscreen+qwerty no slide"
**tech**
        size    (small \$l \$w m)
        termOrder         (x y z)
        namePrefix        "S"
        prop       (nil \$l l \$w w)
 **spec**
        term          (nil x \:1 y \:2 z \:3)
        termOrder         (x y z)

我想要一个表格,左边的名字作为标题,右边的数据作为它的值。

.                                         tech                            spec   
CELL   model   description   size   termOrder   namePrefix  prop  termOrder Term       

这些是标题,我想要这些标题下方的相应值。我尝试使用我用于另一种制表的代码:

my $pr      = "%-12s";  
my @headers = qw/............../;  
my %names;

while (<DATA>) {          

    chomp;          
    my $line = <DATA>;          
    %{$names{$_}} = split /=|\s+/, $line;  
} 

printf $pr x @headers . "\n", @headers;  

for (keys %names) {

    my @ds = ($_);          
    for my $k (@headers[1 .. $#headers]) {     

        my $v = $names{$_}->{$k};                 
        push @ds, $v ? $v : '-';
    }         
    printf $pr x @ds . "\n", @ds;
 } 

这不会产生所需的结果,所以请帮我解决这个问题。

4

1 回答 1

3

这确实不是最简单的任务,而且像往常一样,有不止一种方法可以做到这一点。这是一个。如果有任何问题,请随时提出,因为代码太多,无法解释所有内容。

但是,如果这是我的任务,我会选择 HTML 作为输出格式来摆脱所有这些宽度计算——还有舒适的 JS 工具来对这些表格进行排序。如果你真的想只用文本做这样的事情,也许“好的旧格式”适合你。;)

代码

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'switch';
use List::Util 'sum';

# preparations
my @blocks; # array for all data block
my $block;  # the data block we're working with
my $part;   # the data block part we're working with

# read things and decide what to do
for (<DATA>) {
    chomp;

    # start of a new data block, first part: main
    when (/CELL\s*=\s*"?([^"]+)"?/) {
        $part   = 'main';
        $block  = {
            $part   => {CELL => $1},
            tech    => {},
            spec    => {},
        };
        push @blocks, $block;
        next;
    }

    # start a new part
    when (/\*\*(tech|spec)\*\*/) {
        $part = $1;
        next;
    }

    # fill parts
    when (/"?(\w+)"?\s+"?([^"]+)"?/) {
        $block->{$part}{$1} = $2;
        next;
    }
}

# prepare output
my %columns = (
    main => [
        {name => 'CELL',        length =>  5},
        {name => 'model',       length =>  5},
        {name => 'description', length => 30},
    ],
    tech => [
        {name => 'size',        length => 20},
        {name => 'termOrder',   length => 10},
        {name => 'namePrefix',  length => 10},
        {name => 'prop',        length => 20},
    ],
    spec => [
        {name => 'term',        length => 30},
        {name => 'termOrder',   length => 10},
    ],
);

# part legend
foreach my $part (qw(main tech spec)) {
    my $width = sum map {$_->{length} + 2} @{$columns{$part}};
    print $part . ' ' x ($width - length $part);
}
print "\n";

# column legend
foreach my $part (qw(main tech spec)) {
    foreach my $column (@{$columns{$part}}) {
        my ($name, $length) = @{$column}{qw(name length)};
        print $name . ' ' x ($length - length($name) + 2);
    }
}
print "\n";

# print each block in columns
foreach my $block (@blocks) {
    foreach my $part (qw(main tech spec)) {
        foreach my $column (@{$columns{$part}}) {
            my $value = $block->{$part}{$column->{name}};
            print $value . ' ' x ($column->{length} - length($value) + 2);
        }
    }
    print "\n";
}

__DATA__
CELL    = "abc"
        "model"         "abc"
        "description"   "qwerty+keypad with slide"
**tech**
        size    (big \$l \$w m)
        termOrder         (x y z)
        namePrefix        "S"
        prop       (nil \$l l \$w w)
    **spec**
        term      (nil C \:1 B \:2 E \:3)
        termOrder         (x y z)
***********************************************************
 CELL    = "efg"
        "model"        "efg"
        "description"  "touchscreen+qwerty no slide"
**tech**
        size    (small \$l \$w m)
        termOrder         (x y z)
        namePrefix        "S"
        prop       (nil \$l l \$w w)
 **spec**
        term          (nil x \:1 y \:2 z \:3)
        termOrder         (x y z)

输出

main                                          tech                                                                spec                                        
CELL   model  description                     size                  termOrder   namePrefix  prop                  term                            termOrder   
abc    abc    qwerty+keypad with slide        (big \$l \$w m)       (x y z)     S           (nil \$l l \$w w)     (nil C \:1 B \:2 E \:3)         (x y z)     
efg    efg    touchscreen+qwerty no slide     (small \$l \$w m)     (x y z)     S           (nil \$l l \$w w)     (nil x \:1 y \:2 z \:3)         (x y z)     
于 2012-09-20T14:26:42.407 回答