At any rate, on to searching. There are several ways to search for data. If you're searching a single file, you can either loop through each record one at a time and try matching for the data you're looking for, or you can use perl's grep() function to search all the data at once. Which of these you use depends on your program.
Say you have a product database, like this one (from our last lesson):
1101|Book of Ra|24.95|IN 1102|Fnord Hunting|12.95|OUT 1210|Illuminatus|14.95|IN 1215|Conspiracy Theories|19.95|IN 1422|Principia Discordia|9.95|IN
Suppose you want to let someone search the database for a book title, or part of a title. You'd have a simple form, something like:
Then, your cgi will read the entire data file and use Perl's grep function to search for the data. The actual syntax for grep is:@results = grep(/pattern/,@listname);The
/pattern/ is a regular expression for the pattern you're matching on.Here's an example:
#!/usr/bin/perl
$datafile = "data.txt";
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/~!/ ~!/g;
$FORM{$name} = $value;
}
$searchstr = $FORM{'book'};
open(INF,$datafile);
@mydata = <INF>;
close(INF);
print "Content-type:text/html\n\n";
print "<html><head><title>Search Results</title></head>\n";
print "<body><h3>Search Results</h3>\n";
@results = grep(/$searchstr/,@mydata);
if ($#results >= 0) {
foreach $i (@results) {
chomp($i);
($stocknum,$name,$price,$status) = split(/\|/,$i);
print "<b>$name</b> ($stocknum) - \$$price<br>\n";
}
}
else {
print "No results found.<p>\n";
}
print "</body></html>\n";
This example will work. Unfortunately it will also match things in other fields, as well - for example, if your visitor enters a number (try entering "12"), they could get back a book matching that stock number, or even that price. To check against that, you could modify the above script by testing the results lines against the field you want people to search on. Here's an example (just swap out this code for the results loop in your previous script):
@results = grep(/$searchstr/,@mydata);
$found = 0;
if ($#results >= 0) {
foreach $i (@results) {
chomp($i);
($stocknum,$name,$price,$status) = split(/\|/,$i);
if ($name =~ $searchstr) {
print "<b>$name</b> ($stocknum) - \$$price<br>\n";
$found = 1;
}
}
}
else {
print "No results found.<p>\n";
}
if ($found == 0) {
print "No results found.<p>\n";
}
And here's the form using the above example:One final way to search a file would be to not use grep at all, but instead simply loop through each element in the file and try matching for the data you are looking for. Replace the results loop in the first script with this code:
$count = 0;
foreach $i (@mydata) {
chomp($i);
($stocknum,$name,$price,$status) = split(/\|/,$i);
if ($name =~ $searchstr) {
print "<b>$name</b> ($stocknum) - \$$price<br>\n";
$count = $count + 1;
}
}
$nicestr = "books";
if ($count == 1) {
$nicestr = "book";
}
print "<p>$count $nicestr found.<p>\n";
And here's the form using the above example: