Perl script called via html?

fabiano petrone
fabiano petrone used Ask the Experts™
on
Hello,
I've a little script that processes csv tab-delimited files and outputs other csv modified following our needs.

The script (called arch.pl)  is the following:

#!/usr/bin/perl

# open(FD_IN, "<STDIN") || die "Errore apertura standard input";
while (<STDIN>) {
	$Riga = $_;
	$Riga =~ s/\n//;
	$Riga =~ s/\r//;
	@Campi = split("\t", $Riga);
	#eliminazione di cragna importata da filemaker
    $Campi[1] =~ s///g if ( $Campi[1] ne "" );
	$Campi[4] =~ s///g if ( $Campi[4] ne "" );
	$Campi[5] =~ s///g if ( $Campi[5] ne "" );
	
	#eliminazione di spazi bianchi iniziali e finali
	sub  trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
	    for (my $i=0; $i <= 9; $i++) {
       $Campi[$i] = trim($Campi[$i]);
    }
	#tengo solo la prima lettera della sezione
	$Campi[7] = substr($Campi[7], 0, 1);
	printf("\"".$Campi[0]."\"|\"".$Campi[1]."\"|\"".$Campi[2]."\"|\"".$Campi[3]."\"|\"".$Campi[4]."\"|\"".$Campi[5]."\"|\"".$Campi[6]."\"|\"".$Campi[7]."\"|\"".$Campi[8]."\"|\"".$Campi[9]."\"\n");
	$cntRecord++;
}
# close(FD_IN);	

Open in new window


now the script is called in console via:

> perl arch.pl<input.csv>output.csv

Open in new window


the question is: can I embed this code in a .cgi web page and pass to it the input.csv with an upload file form?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Perl programmer, author and trainer
Commented:
Something like this will work. I hope you don't mind, but I've modernised your Perl a bit too.

#!/usr/bin/perl

# ALWAYS USE THESE
use strict;
use warnings;

use CGI;
use CGI::Carp qw[fatalsToBrowser];

my $cgi = CGI->new;

if ($cgi->param) {
  # do stuff
  print $cgi->header('text/plain');
  my $upload_fh = $cgi->upload('file');
  process_filehandle($upload_fh);
} else {
  print $cgi->header;
  print while <DATA>;
}


# Move this stuff into a subroutine
sub process_filehandle {
  my ($fh) = @_;

  # Define variable
  my $cntRecord = 0;

  while (<$fh>) {
    # Removed pointless $Riga variable
    # use chomp to remove newline
    chomp;
    # Declare variables with my
    # split takes a regex, not a string.
    my @Campi = split /\t/;

    #eliminazione di cragna importata da filemaker
    # Do repetitive stuff in a loop
    for my $i (1, 4, 5) {
      $Campi[$i] =~ s///g if $Campi[$i] ne "";
    }

    #eliminazione di spazi bianchi iniziali e finali
    # foreach loop is easier to understand
    foreach my $i (0 .. 9) {
      $Campi[$i] = trim($Campi[$i]);
    }

    #tengo solo la prima lettera della sezione
    $Campi[7] = substr($Campi[7], 0, 1);

    # Use qq[...] to make this clearer
    # Use print, not printf
    print(qq["$Campi[0]"|"$Campi[1]"|"$Campi[2]"|"$Campi[3]"|"$Campi[4]"|"$Campi[5]"|"$Campi[6]"|"$Campi[7]"|"$Campi[8]"|"$Campi[9]"\n]);
    $cntRecord++;
  }
}

# Move subroutine definition out of loop
sub  trim {
  my $s = shift;
  $s =~ s/^\s+|\s+$//g;
  return $s
};

__END__
<html>
  <head>
    <title>Arch</title>
  </head>
  <body>
    <h1>Arch</h1>
    <form method="post" enctype="multipart/form-data">
      <p>File to upload: <input type="file" name="file"></p>
      <p><input type="submit" name="submit" value="Submit"></p>
    </form>
  </body>
</html>

Open in new window

nociSoftware Engineer
Distinguished Expert 2018

Commented:
You will need your webserver to allow for perl execution  using fastcgi or cgi.
Great looking answer, Dave!  Much better than I would have done.

But instead of doing this, which seems so repetitive:
print(qq["$Campi[0]"|"$Campi[1]"|"$Campi[2]"|"$Campi[3]"|"$Campi[4]"|"$Campi[5]"|"$Campi[6]"|"$Campi[7]"|"$Campi[8]"|"$Campi[9]"\n]);

Open in new window

What would be wrong with something like this?:
print qq["] . join(qq["|"], @Campi) . qq["]

Open in new window

Both seem to give the same output.

Or is there a more elegant way to get "quotes" around each element and then use "join" to join them with just a pipe (and no quotes) as the delimiter?  I'm talking about a way of removing the need to have the leading quote I put before the join, and the trailing quote after.


fabiano, are you sure you even need "quotes" around each element?  You already have pipes between them.  Is it because the elements might contain pipes?
Dave CrossPerl programmer, author and trainer

Commented:
@tel2:

Yes, I think I'd stopped improving the Perl code at that point :-)

I think I would use a combination of map and join.

say join '|', map { qq["$_"] } @Campi;

Open in new window

Good answer Dave - thanks again.

> "Yes, I think I'd stopped improving the Perl code at that point :-)"
Can't blame you for that.  Sorry to drag you back into it.

I've just realised that this suggestion of mine:
print qq["] . join(qq["|"], @Campi) . qq["];

Open in new window

could have been written with single q's like this, since no interpolation is required in this case:
print q["] . join(q["|"], @Campi) . q["];

Open in new window

or with no q's like this:
print '"' . join('"|"', @Campi) . '"';

Open in new window

The latter being more concise and would be my preference unless I was doing a one-liner where the single quotes would be interpreted as the end of the code.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial