What is the issue with this CGI/HTML/Perl program?

2019-09-20 12:14发布

问题:

I am using XAMMP Apache Server. There is a text file named 'animal.txt' containing the name of an animal on each line, with a basic description.

I am trying to write a Perl program, using HTML and CGI. The aim of the program is to have the user search an animal name, using a HTML form. This will then link to a Perl program which loops through the animal.txt file and reads the file line by line. The program will take any line that matches the users search from the original HTML form, and print all animals containing the same name.

So far this is where I am :

(Clientside form)

#!\xampp\perl\bin\perl.exe
use CGI qw/:standard/; # load standard CGI routines
use CGI::Carp('fatalsToBrowser'); 

print header(); # create the HTTP header
print  <<HTML
<head>
  <title>Shop Here</title>
 </head>
 <body>

<h1>Animal list search</h1>

     A basic form  <br />

  <form action="dumpsVar2.pl"> 
    Search:     <input type="text", name="Search" size=5><br><br>
    Submit:     <input type="submit" name="select" size="7"><br>
    </form> 
  </body>
 </html>
 HTML

And then the perl program: (Server-Side) #!\xampp\perl\bin\perl.exe

use CGI qw(:standard);
use CGI::Carp('fatalsToBrowser'); 
$query = new CGI;

@parameters = $query -> param;
print header, start_html("Parameters");
print "$0 was passed these parameters:<br>  <br> ";

foreach $name (@parameters) {
    $value = $query -> param($name);
    print p("$name = $value"); 
} 
$inFile = "animal.txt";
open (IN, $inFile) or die "Can't find file: $inFile";

@animals = (<IN>);
$item = param;
foreach $line (<IN>) {
    if ($line =~ /$item/) {
        print "$item";
    }
}

print end_html;

回答1:

Several issues here, but the crux of the matter is this code.

@animals = (<IN>);
$item = param;
foreach $line (<IN>) {
    if ($line =~ /$item/) {
        print "$item";
    }
}

Let's look at each line in turn:

@animals = (<IN>);

This reads all of the data from IN into the array @animals. It also leaves IN's file pointer at the end of the file. Any further attempts to read data from IN will fail.

$item = param;

If you call param with no arguments, you get a list of the parameter names that were found in the CGI request. As you're assigning this list to a scalar value, this behaviour changes and you'll get the number of parameters. In your system this will always be 1. So $item contains the value 1.

foreach $line (<IN>) {

Remember how you read all of the data from IN a couple of lines back? Well you're trying to read more data from it here. And that's not going to work. I think you probably wanted @animals here, not <IN>. Currently your foreach is never executed as on the first iteration the call to <IN> returns undef - which is false.

if ($line =~ /$item/) {

Let's assume that you've replaced <IN> with @animals in your foreach loop - so that the loop body is actually executed. This still isn't doing what you wanted. Remember that $item contains 1 rather than the name of an animal to search for. And I doubt that you have an animal called "1".

What you probably want is something more like this:

my $animal = param('Search');
while (<IN>) {
    print if /$animal/;
}

I'd also point out that learning CGI in 2014 is pretty ridiculous. You would be far better off looking at a simple Perl web framework like Web::Simple or Dancer.



回答2:

I think your problem is

$item = param;

Which is putting the number of parameters in your form, in this case 2, into $item. I doubt you have an animal named 2

Change it to

$item = param('Search');