【问题标题】:How do I convert CSV into an HTML table using Perl?如何使用 Perl 将 CSV 转换为 HTML 表格?
【发布时间】:2010-09-17 00:58:42
【问题描述】:

在我的代码中,我想以表格形式查看 CSV 中的所有数据,但它只显示最后一行。 1号线和2号线呢?这是数据:

1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh

代码如下:

#! /usr/bin/perl
print "Content-type:text/html\r\n\r\n";
use CGI qw(:standard);
use strict;
use warnings;

my $line;
my $file;
my ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19);

$file='MyFile.txt';
open(F,$file)||die("Could not open $file");
while ($line=<F>)
{

($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19)= split ',',$line;

}

close(F);

print "<HTML>";
print "<head>";
print "<body bgcolor='#4682B4'>";
print "<title>FUSION SHIFT REPORT</title>";
print "<div align='left'>";
print "<TABLE CELLPADDING='1' CELLSPACING='1' BORDER='1' bordercolor=black width='100%'>";
print "<TR>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>RECORD No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>DATE</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TIME</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>DEVICE NAME</td>";
print "<td bgcolor='#00ff00'><font size='2'>TEST PROGRAM</td>";
print "<td bgcolor='#00ff00'><font size='2'>DEVICE FAMILY</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>DIE LOT</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>LOADBOARD</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER </td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>SERIAL NUMBER</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TESTER CONFIG</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td bgcolor='#00ff00'><font size='2'>PACKAGE</td>";
print "<td bgcolor='#00ff00'><font size='2'>SOCKET</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 1</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 2</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 3</td>";
print "</tr>";
print "<TR>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f1</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f2</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f3</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f4</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f5</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f6</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f7</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f8</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f9</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f10</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f11</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f12</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f13</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f14</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f15</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f16</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f17</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f18</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f19</TD>";
print "</tr>";

print "</TABLE>";

print "</body>";
print "<html>";

【问题讨论】:

    标签: html perl html-table


    【解决方案1】:

    HTML::Template 会让您的生活更轻松。这是我使用精简模板的方法。

    #!/usr/local/bin/perl
    
    use strict;
    use warnings;
    
    use HTML::Template;
    
    my @table;
    while (my $line = <DATA>){
        chomp $line;
        my @row = map{{cell => $_}} split(/,/, $line);
        push @table, {row => \@row};
    }
    
    my $tmpl = HTML::Template->new(scalarref => \get_tmpl());
    $tmpl->param(table => \@table);
    print $tmpl->output;
    
    sub get_tmpl{
        return <<TMPL
    <html>
    <TMPL_LOOP table>
    <tr>
    <TMPL_LOOP row>
    <td><TMPL_VAR cell></td></TMPL_LOOP>
    </tr></TMPL_LOOP>
    </html>
    TMPL
    }
    
    __DATA__
    1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
    2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
    3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh
    

    【讨论】:

      【解决方案2】:

      您只看到最后一行的原因是您在读取整个文件后运行打印并在读取下一行时丢弃每一行。

      说实话,这段代码有很多问题。我会提到几个并在下面的代码 sn-p 中解决这些问题。

      1. 不要自己解析 CSV 数据(拆分)。使用 Text::CSV 或 -- 如果您需要更好的性能 -- Text::CSV_XS
      2. 您的 HTML 无效。您不会关闭所有标签,特别是标题应该在头部,而不是正文。
      3. 您应该使用模板模块将表格数据插入网页。示例:HTML::TemplateTemplate Toolkit
      4. 至少,使用函数来抽象出冗余代码。
      5. 更好的是,使用数据的格式也是数据这一事实。这就是为什么它应该被这样对待。
      6. 如果你发现你声明了很多带有数字的变量($f1,$f2,...),你真的想要一个数组:@fields = split /,/, $line;

      use strict;
      use warnings;
      use CGI qw();
      use Text::CSV;
      
      my $cgi = CGI->new();
      print $cgi->header();
      
      my $file ='MyFile.txt';
      
      # should really use a templating module from CPAN,
      # but let's take it step by step.
      # Any of the following would fit nicely:
      # - Template.pm (Template Toolkit)
      # - HTML::Template, etc.
      my $startHtml = <<'HERE';
      <html>
      <head> <title>FUSION SHIFT REPORT</title> </head>
      <body bgcolor="#4682B4">
      <div align="left">
      <table cellpadding="1" cellspacing="1" border="1" bordercolor="black" width="100%">
      HERE
      my $endHtml = <<'HERE';
      
      </table>
      
      </body>
      <html>
      HERE
      
      my @columns = (
        { name => 'RECORD No.', width => 12 },
        { name => 'TESTER No.', width => 12 },
        { name => 'DATE', width => 12 },
        { name => 'TIME', width => 13 },
        { name => 'DEVICE NAME', width => 11 },
        { name => 'TEST PROGRAM' },
        { name => 'DEVICE FAMILY' },
        { name => 'SMSLOT', width => 13 },
        { name => 'DIE LOT', width => 13 },
        { name => 'LOADBOARD', width => 12 },
        { name => 'TESTER', width => 12 },
        { name => 'SERIAL NUMBER', width => 12 },
        { name => 'TESTER CONFIG', width => 13 },
        { name => 'SMSLOT', width => 11 },
        { name => 'PACKAGE' },
        { name => 'SOCKET' },
        { name => 'ROOT CAUSE 1', width => 13 },
        { name => 'ROOT CAUSE 2', width => 13 },
        { name => 'ROOT CAUSE 3', width => 13 },
      );
      
      
      my $csv = Text::CSV->new();
      open my $fh, '<', $file
        or die "Could not open file '$file': $!"; # should generate a HTML error here
      
      # print header
      print $startHtml;
      print_table_header(\@columns);
      
      while (defined(my $line = <$fh>)) {
        $csv->parse($line);
        # watch out: This may be "tainted" data!
        my @fields = $csv->fields();
        @fields = @fields[0..$#columns] if @fields > @columns;
        print_table_line(\@fields);
      }
      
      close $fh;
      
      print $endHtml;
      
      
      
      
      sub print_table_header {
        my $columns = shift;
        print "<tr>\n";
        foreach my $column (@$columns) {
          my $widthStr = (defined($column->{width}) ? ' width="'.$column->{width}.'"' : '');
          my $colName = $column->{name};
          print qq{<td$widthStr bgcolor="#00FF00"><font size="2">$colName</font></td>\n};
        }
        print "</tr>\n";
      }
      
      sub print_table_line {
        my $fields = shift;
        print "<tr>\n";
        foreach my $field (@$fields) {
          print qq{<td bgcolor=\"#ADD8E6\"><font size="2">$field</font></td>\n};
        }
        print "</tr>\n";
      }
      

      【讨论】:

        【解决方案3】:

        这不是最强大的解决方案,事实上,如果值中包含逗号,则会出现一些非常糟糕的故障,但它为我完成了这项工作:

        (CSV 数据位于名为 $content 的变量中)

        $content =~ s#\n#</td></tr><tr><td>#g;
        $content =~ s#,#</td><td>#g;
        $content = "<table><tr><td>$content</td></tr></table>";
        

        【讨论】:

          【解决方案4】:
          $f1,$f2,$f3,$f4
          

          任何时候你看到类似警报的代码都应该响起。使用数组。

          【讨论】:

          • 这应该是一条评论。它不会尝试回答问题。
          【解决方案5】:

          请关闭您的 标签。仅仅因为浏览器会处理它们的缺失并不意味着它们没有价值。

          【讨论】:

            【解决方案6】:

            您需要在while 循环输出表格行,因为那是您正在读取行的地方。

            所以改一下代码吧

            • 输出表头
            • 逐行读取文件输出表行
            • 输出表格页脚

            如果稍微简化一下,您的循环可能会如下所示...

            while ($line=<F>)
            {  
                print "<tr>";
                my @cells= split ',',$line;
                foreach my $cell (@cells)
                {
                   print "<td>$cell</td>";
                }
                print "</tr>";
            }
            

            【讨论】:

              【解决方案7】:

              请允许我用一个更小的例子来演示。

              my $f;
              while ($line = <F>) {
                  $f = $line;
              }
              print $f;
              

              上面的代码会读取文件F的每一行,将每一行赋值给变量$f。每次它分配一个新行时,前一行都会被覆盖。当它到达文件末尾时,它会打印一次$f 的值。

              my $f;
              while ($line = <F>) {
                  $f = $line;
                  print $f;
              }
              

              上面的代码在循环中包含print,因此print 将针对输入的每一行运行。您需要对代码进行类似的修改以获得您期望的输出。

              【讨论】:

                猜你喜欢
                • 2010-11-27
                • 1970-01-01
                • 2011-02-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多