كيف أقوم بتحويل ملف CSV إلى جدول HTML باستخدام لغة Perl؟

StackOverflow https://stackoverflow.com/questions/200140

  •  03-07-2019
  •  | 
  •  

سؤال

في الكود الخاص بي، أريد عرض جميع البيانات من ملف 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::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

نصائح أخرى

تحتاج إلى إخراج صفوف الجدول داخل حلقة while، حيث أن هذا هو المكان الذي تقرأ فيه السطور.

لذا قم بتغيير الكود بحيث يكون

  • رؤوس جدول المخرجات
  • يقرأ سطر الملف سطرًا ويخرج صفوف الجدول
  • تذييل جدول المخرجات

إليك كيف قد تبدو حلقتك إذا تم تبسيطها قليلاً...

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

في أي وقت ترى فيه رمزًا كهذا، يجب أن تنطلق أجراس الإنذار.استخدم مصفوفة.

اسمحوا لي أن أعرض مع مثال أصغر.

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

سوف يقرأ الكود أعلاه كل سطر من الملف F، ويعين كل سطر للمتغير $f.في كل مرة يتم تعيين سطر جديد، يتم الكتابة فوق السطر السابق.عندما يصل إلى نهاية الملف، فإنه يطبع قيمة $f مرة واحدة.

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

الكود أعلاه يحتوي على print داخل الحلقة، لذلك print سيتم تشغيله لكل سطر من الإدخال.ستحتاج إلى إجراء تعديل مماثل على التعليمات البرمجية الخاصة بك للحصول على المخرجات التي تتوقعها.

السبب وراء رؤيتك للسطر الأخير فقط هو أنك قمت بتشغيل النسخة المطبوعة بعد قراءة الملف بأكمله وتجاهل كل سطر عند قراءة السطر التالي.

لنكون صادقين، هناك أشياء مختلفة خاطئة في هذا الرمز.سأذكر زوجين وأتناولهما في مقتطف الشفرة أدناه.

  1. لا تقم بتحليل بيانات CSV بنفسك (التقسيم).يستخدم النص::CSV أو - إذا كنت بحاجة إلى أداء أفضل - النص::CSV_XS.
  2. HTML الخاص بك غير صالح.لا تغلق جميع العلامات، وعلى وجه الخصوص، يجب أن يكون العنوان في الرأس، وليس في النص.
  3. يجب عليك استخدام وحدة القوالب لإدراج البيانات الجدولية في صفحة الويب.أمثلة: HTML::قالب أو مجموعة أدوات القالب.
  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";
}

الرجاء إغلاق علامات <font> الخاصة بك.فقط لأن المتصفح سيتعامل مع نقصها لا يعني أنها ليست ذات قيمة لتضمينها.

هذا ليس الحل الأقوى، في واقع الأمر هناك بعض الإخفاقات السيئة جدًا إذا كانت لديك فواصل داخل القيم، لكنه قام بالمهمة نيابةً عني:

(بيانات CSV موجودة في متغير يسمى $content)

$content =~ s#\n#</td></tr><tr><td>#g;
$content =~ s#,#</td><td>#g;
$content = "<table><tr><td>$content</td></tr></table>";
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top