用于制表的Perl程序

时间:2012-08-08 01:46:18

标签: regex perl

F1.txt

tom
x
a=1 b=2 c=3 d=4 e=5 
y
b=11 r=12
bob

a=6 b=7 c=8 e=10

结果

F2.txt

.            X         Y
name  a  b  c  d  e  b   r

tom   1  2  3  4  5  11  12

bob   6  7  8  -  10 -   -

你能帮我解决这个问题吗?我有一个文件F1.txt。我的工作是将该文件转换为示例F2.txt中所示的格式。我尝试通过删除Tom和Bob之后的所有字符串值除了F1.txt中的数值,然后连接。这是代码:

use strict;

open (file100,"< data.txt");
open (file101,">>F3.txt");

my @array = < file100>;

print file101 "name    a    b      c      d     e\n\n";
print file101 "tom @array[1]\n\n";
print file101 "bob @array[3]\n\n";

这里是data.txt:

tom

1 2 3 4 5

bob 

6 7 8 10

我使用此代码获得的输出是:

F3.txt

name  a  b  c  d  e

tom   1  2  3  4  5

bob   6  7  8  10

预期输出应该如F2.txt中所示,但不像F3.txt

3 个答案:

答案 0 :(得分:4)

#!/usr/bin/env perl

my $pr = "%-12s";
my @headers = qw/name a b c d e/;
my %names;
while (<DATA>) {
    chomp;
    s/^\s+//g;
    s/\s+$//g;
    my $line = <DATA>;
    $line =~ s/^\s+//g;
    $line =~ s/\s+$//g;
    %{$names{$_}} = split /\s*=\s*|\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;
}

__DATA__
 tom
 a = 10.1 b = 2 c = 300.89 d=4145 e=55
bobby
 a= 60 b = 74.2 c = 8 e = 10.25

输出:

name    a       b       c       d       e       
tom     1       2       3       4       5       
bob     6       7       8       -       10      

答案 1 :(得分:3)

这将按照您的要求进行

use strict;
use warnings;

my %data;
my @names;

while (<DATA>) {
  next unless /\S/;
  if (/=/) {
    %{ $data{$names[-1]} } = /[^\s=]+/g;
  }
  else {
    push @names, /(\S+)/;
  }
}

my %keys = map %$_, values %data;
my @keys = sort keys %keys;

printf "%-6s %s\n\n", 'name', join '  ', @keys;
printf "%-6s %s\n\n", $_, join '  ', map $_ // '-', @{$data{$_}}{@keys} for @names;

__DATA__
tom

a=1 b=2 c=3 d=4 e=5

bob

a=6 b=7 c=8 e=10

<强>输出

name   a  b  c  d  e

tom    1  2  3  4  5

bob    6  7  8  -  10

<强>更新

对于旧版本(在v5.10之前),Perl会将定义的或运算符//视为错误的正则表达式匹配。对于这些平台,第二个printf语句可以像这样编写

printf "%-6s %s\n\n", $_, join '  ', map { defined $_ ? $_ : '-' } @{$data{$_}}{@keys} for @names;

答案 2 :(得分:1)

为了您的理解,我正在采取长期措施:

use strict;
use warnings;

my %hash;
my @vals;
my $key;
my $val;
my $name;
my @headings;
my $file100;

open ($file100, "<", "data.txt");


while (<$file100>)
{
        chomp;
        next if (! m/\S/);
        if (m/=/)
        {
            @vals = $_ =~  /(.+)=(.+)\b/g;
            while (@vals)
            {
                $key = shift @vals;
                if (!grep(/^$key$/, @headings))
                {
                    push (@headings, $key);
                }

                $val = shift @vals;
                $hash{$name}{$key} = $val;
            }
        } else {
           $name = $_;
}

print "name\t" . join ("\t", @headings) . "\n\n";
for my $key1 (keys %hash)
{
    print $key1;
    for (@headings)
    {
        if (defined $hash{$key1}{$_})
        {
            print "\t" . $hash{$key1}{$_};
        } else
        {
            print "\t-";
        }
    }
    print "\n\n";
}

你需要拿一本Perl书并进行研究。