PERL을 사용하여 CSV를 HTML 테이블로 어떻게 변환합니까?
-
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 :: 템플릿은 당신의 삶을 훨씬 쉽게 만들 것입니다. 여기 컷 다운 템플릿이있는 내 이동이 있습니다.
#!/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
입력의 각 라인에 대해 실행됩니다. 당신은 당신이 기대하는 출력을 얻기 위해 코드와 유사한 수정을하고 싶을 것입니다.
마지막 줄 만 보았던 이유는 전체 파일을 읽고 다음 줄을 읽을 때 각 줄을 버린 후 인쇄물을 실행했기 때문입니다.
솔직히 말해서, 해당 코드에는 여러 가지 문제가 있습니다. 나는 몇 가지를 언급하고 아래 코드 스 니펫에있는 것들을 다루겠습니다.
- CSV 데이터를 직접 구문 분석하지 마십시오 (분할). 사용 텍스트 :: CSV 또는 더 나은 성능이 필요한 경우 - 텍스트 :: csv_xs.
- HTML이 유효하지 않습니다. 당신은 모든 태그를 닫지 않으며 특히 제목은 머리에 있어야하지만 몸매는 아닙니다.
- 웹 페이지에 테이블 데이터를 삽입하려면 템플릿 모듈을 사용해야합니다. 예 : html :: 템플릿 또는 템플릿 툴킷.
- 최소한 함수를 사용하여 중복 코드를 추상화하십시오.
- 더 나은 것은 데이터의 형식이 데이터라는 사실을 사용하십시오. 그렇기 때문에 그것이 그렇게 취급되어야합니다.
- 숫자가 첨부 된 많은 변수를 선언한다는 것을 알게된다면 (
$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";
}
u003Cfont>태그를 닫으십시오. 브라우저가 부족을 처리한다고해서 포함하는 것이 가치가 없다는 것을 의미하지는 않습니다.u003C/font>
이것은 가장 강력한 솔루션이 아니며, 사실의 문제는 쉼표 안에 쉼표가 있다면 꽤 불쾌한 실패를 가지고 있지만, 그것은 나에게 일을했습니다.
(CSV 데이터는 $ 컨텐츠라는 변수입니다)
$content =~ s#\n#</td></tr><tr><td>#g;
$content =~ s#,#</td><td>#g;
$content = "<table><tr><td>$content</td></tr></table>";