tags:

views:

134

answers:

5

I need some help making this script... so far I think it should look something like this (I tend to use AWK a lot)

#!/usr/bin/perl -w
@filelist=(
file1,
file2,
file3
)
print ("<html>");
foreach $filelist {
  print ("<table>";
  print ("<td>"$filelist"</td>")
  foreach [line in the file]
    print ("<td>"$1, $2"</td>");
  }
  print ("</table>";
}
print ("</html>");

So I want the script to go to each file, print the filename, and then for each line print two strins in a <td>

Am I on the right track?

Also, I realised the AWK I wrote needed a couple of IF statements - I believe it should look like this

while(<F_IN>) {
if ($1>=2) {
    print "<td class=\"green\" title=\""$1,$2"\">"
}
if ($1>=1) {
    print "<td class=\"amber\" title=\""$1,$2"\">"
}
if ($1>=0) {
    print "<td class=\"red\" title=\""$1,$2"\">"
}
+7  A: 

Your code doesn't really make any sense. I suggest taking a look at a basic Perl intro before trying anything more complicated.

That said, what you're probably trying to do is something like this:

#!/usr/bin/perl

use strict;      # never forget this line
use warnings;    # or this one, it's better than the -w flag

use CGI qw(:standard);   # this gives us convenient functions for outputting
                         # HTML, plus other stuff for processing CGI requests

my @filelist = ( 'file1', 'file2', 'file3' );

print header;
print start_html;
print start_table;

foreach my $file( @filelist ) { 
    print Tr( td( $file ) );
}

print end_table;
print end_html;

For the (extensive) documentation for the CGI module, see CGI at CPAN.

Edit

If you want the content of each file in the table, then you'll need to read each file into a variable inside the loop. Here's an example of how you could do it:

foreach my $file( @filelist ) { 
    open my $fh, $file or die "Could not open $file: $!";

    local $/ = undef;   # this allows us to slurp the whole file at once
    my $filedata = <$fh>;

    print Tr( td( $filedata ) );
}

Some more docs that you should read: Perl open() tutorial, and all about slurping.

friedo
wow, you really know perl!Thanks for this.Four questions:1 - do I need the quote marks around the file name?2 - If I want to open the files to parse them line by line, do I need to do the whole "open (handle "$filename");, and how do I reference part of the array?3 - I've edited my original request, and I've used the $1, $2 I know from AWK - will this reference the string on each line in order?4 - can I (as with AWK) then output this to a .html file with something like "perl myfile > page.html"?
Soop
+1 @Friedo: I think he wants the content of those files in the `td`s. @Soop you've got to actually try learning the language a little bit before doing complicated stuff.
Sinan Ünür
By default print goes to STDOUT, so you can do any normal redirection.You can open a handle in your script and print to it `print $out "stuff to print"`. Regrettably, you can also do `select $out; print 'stuff';` but DON'T. This method kills kittens. `select` can be used to set the default handle for `print` and several special variables. Don't use it that way, ever. If you see it in the docs, pretend you didn't. So open an handle and print to it with `print FILEHANDLE LIST`, or redirect your output.
daotoad
+3  A: 

Run your code and read the error messages. You have multiple syntax errors.

Whatever tutorial you are reading does not give you some important advice:

#!/usr/bin/perl 

use strict;    # Always, until you know when to turn it off--and then in a limited scope.
use warnings;  # see perllexwarn for why this is better than -v  

# you need to quote those bare words.  qw is a handy quoting operator.  See perlop.
my @filelist = qw(  
    file1 
    file2
    file3
);             # added semicolon 

# use a heredoc for big chunks of text.
# your html is seriously bogus.  Fixed somewhat.
print <<'ENDHTML';
<html>
   <head>
   </head>
   <body>
ENDHTML

# $filelist does not exist.
# fixed syntax of foreach
foreach my $file ( @filelist ) {

  # do you really want a new table for each file?
  print "<table>\n";

  # need to escape your quotes
  print "<tr><td>\"$file\"</td></tr>";

  # open a file handle.
  # use lexical handles instead of old style global handles.
  # use 3 argument open instead of 2 argument style
  open( my $fh, '<', $file);

  # $fh evaluates to true if we were able to open the file.
  if ( $fh ) {

    # iterate over the file.
    while( my $line = <$fh> ) {
      # where the hell did $1 and $2 come from?
      print "<tr><td>$line</td></tr>";
    }

  }
  else {
      # put the error message in the table instead of the file contents
      print "<tr><td>Error opening file: $!</td></tr>";          
  }

  print "</table>";
}
print "</html>";

Since you didn't test your code, I didn't either. But it should work.

Of course inline HTML is best avoided in all but the most simple, throw-away scripts. If you are doing anything lasting or serious, use a templating system like Template::Toolkit or HTML::Template.

daotoad
Ah thanks for this. I'm not using a tutorial, just what I remember from ages ago and some common sense.As I say, I'm used to AWK where strings are referenced with $1, $2 etc.
Soop
@Soop programming is not about common sense. It is about specifications and syntax first. It is not possible to divine the workings of a computer program by intuition. It is much simpler than that. You get a book, write some toy programs, at least learn the language a little before accepting a job.
Sinan Ünür
When you are starting out, the single most valuable part of perldoc is the Perl Functions by category section of perlfunc. http://perldoc.perl.org/perlfunc.html#Perl-Functions-by-Category You can also get to it by doing `perldoc perlfunc`, and probably `man perlfunc`. You can search for a function on the cli with `perldoc -f funcname` and search the FAQ with `perldoc -q someregexp`. For more perldoc features see `man perldoc`.
daotoad
Ok, look thanks a lot for your help, but there's no need to have a go at me. I accept that I have an erratic way of doing things, but that's just the way I work; I prefer to reverse engineer things if possible etc. I could do this in AWK, but I figured Perl would be more elegant.But seriously, I do appreciate your help.
Soop
@Soop, I think Sinan is trying to tell you to read some basic tutorials and/or TFM instead of asking for help right away. Check out Picking Up Perl for a reasonable, if somewhat dated start: http://www.ebb.org/PickingUpPerl/pickingUpPerl_toc.html
daotoad
@Soop, knowing where to find good tutorials is a big problem when you start learning Perl. Especially since there is a lot of very old material dating from the mid-nineties still on the web, much of it of questionable quality. Ovid's CGI Course is old, but it is very well written and is appropriate to your task, check it out at http://jdporter.perlmonk.org/cgi_course/ If you learn best by example, look at PLEAC - http://pleac.sourceforge.net/
daotoad
Thanks daotaod - I've learned loads already!
Soop
+3  A: 

Use HTML::Template so that you have full control over the HTML and your code is not unreadable. See my answer to another question for an example of how to embed the template in your code. Of course, the same template can exist outside of the script and that's the benefit of separating presentation from logic.

#!/usr/bin/perl

use strict; use warnings;
use autodie;

use HTML::Template;

my @files = qw(file1 file2);
my @files_loop;

for my $file (@files) {
    open my $fh, '<', $file;

    push @files_loop, {
        LINES => [
            map { chomp; length $_ ? {LINE => $_} : () } <$fh>
    ]};
}

my $tmpl = HTML::Template->new(filehandle => \*DATA);
$tmpl->param(FILES => \@files_loop );
print $tmpl->output;

__DATA__
<html>
<body>
<TMPL_LOOP FILES>
<table>
<TMPL_LOOP LINES><tr><td><TMPL_VAR LINE></td></tr></TMPL_LOOP>
</table>
</TMPL_LOOP>
</html>

Output:

C:\Temp> fish.pl
<html>
<body>

<table>
<tr><td>bye bye</td></tr><tr><td>hello</td></tr><tr><td>thank you</td></tr><tr><
td>no translation</td></tr>
</table>

<table>
<tr><td>chao</td></tr><tr><td>hola</td></tr><tr><td>gracias</td></tr>
</table>

</html>
Sinan Ünür
A: 

This is what I came up with from talking you guys - a big thanks to everyone :D

        #!/usr/bin/perl

    use strict;      # never forget this line
    use warnings;    # or this one, it's better than the -w flag

    use CGI qw(:standard);   # this gives us convenient functions for outputting
                             # HTML, plus other stuff for processing CGI requests

    my @filelist=(
'file1',
'file2',
'file3',
'file4',
'file5',
'file6',
    );
    #
    #
    print "<html>\n";
    print "<head>\n";
    print "<link rel=\"stylesheet\" type=\"text/css\" href=\"test.css\">\n";
    print "</head>\n";
    foreach my $file (@filelist) {
        print "<table>\n";
        print "<div>\n";
        print "<tr>\n";
        print  td( $file );
        open( my $fh, '<', $file);
        if ($fh) {
          while( my $line = <$fh> ) {
          chomp $line;
          if (substr($line, 0, 1)>="2") {
            print "<td class=\"green\" title=\"" . $line . "\">\n";
            }
          elsif (substr($line, 0, 1)=="1") {
            print ("<td class=\"amber\" title=\"" . $line . "\">\n");
            }
          elsif (substr($line, 0, 1)=="0") {
            print ("<td class=\"red\" title=\"" . $line . "\">\n");
            }
          }
        }
        print "</tr>\n";
        print "</div>\n";
        print "</table>\n";
    }
    print "</html>";

The HTML needs a little tweaking, and a lot of it is redundant, but it works fine :)

Soop
Okay, but you missed selecting an answer as accepted. Please do so.
Leonardo Herrera
A: 

Some excellent answers above. Here is yet another twist on the theme this time using Markapl based on Soop's answer.

use strict; 
use warnings;
use CGI ();
use Markapl;

my @filelist = qw/file1.txt file2.txt file3/;

template 'web' => sub {
  html {
    head {
      html_link (rel => 'stylesheet', type => 'text/css', href => 'test.css') {}
    }
    body {
      table {
        for my $file (@filelist) {
          open my $fh, '<', $file or next;
          row { 
            for my $title (<$fh>) { 
                chomp $title; 
                cell { $file }
                cell ( class => title_class( $title ), title => $title ) {}
} } } } } } };

print CGI::header();
print main->render( 'web' );

sub title_class {
    my $first_char = substr $_[0], 0, 1;
    return 'green' if $first_char >= 2;
    return 'amber' if $first_char == 1;
    return 'red';
}

I do like these "builder" type approaches. For some more see this SO question CL-WHO-like HTML templating for other languages?

/I3az/

draegtun