perl中的数据列表

时间:2012-09-11 03:28:49

标签: regex perl tabular

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

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;
 } 

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

1 个答案:

答案 0 :(得分:3)

这真的不是最简单的任务,而且总是如此,有多种方法可以做到这一点。这是一个。如果有任何问题,请随意提问,因为解释所有内容的代码实在太多了。

然而,如果这是我的任务,我会选择HTML作为输出格式来摆脱所有这些宽度计算 - 也有舒适的JS工具来排序这些表。如果你真的想用文字做这样的事情,也许“好老formats”适合你。 ;)

代码

#!/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)