saskia
asked on
foreach and faster problem
I use the script below to build a small database of 100 records.
Then they are read out again and each record will be checked if
a value of the array @words is present, if so the
record will be printed.
The problem is that the 'foreach $x (@words){' line doesn't go through
each character/word of @words. I tried it with the parameter sentence 'hello,0,c'.
When I trie to print out the $x value it gives me the value 0 instead of the
current value of @words.
- How can I fix this problem ?
- Also I must make this script faster (the part between the stopwatch lines)
So I hope someone can alter this script to produce faster output.
#!/usr/bin/perl
use CGI;
use DB_File ;
$q=new CGI;
print "Content-type: text/html\n\n";
$sentence=$q->param('sente nce');
@words=split(",",$sentence );
unlink "fruit" ;
tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open file 'fruit': $!\n";
for ($xx=1; $xx<100; $xx++){
$h{$xx} = 'CIS100@é@01@é@Intro@é@to Computing@é@8';
}untie %h ;
$stopwatch_aan=(times)[0];
tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open file 'fruit': $!\n";
while (($h,$line)=each %h){
@line=split('@é@',$line);
foreach $x (@words){
if (grep /$x/,@line){
($Course,$Section,$Title,$ Tiles)=spl it('@é@',$ line);
print qq{Record=$h<br>Course=$Co urse<br>Se ction=$Sec tion<br>Ti tle=$Title <br>Tiles= $Tiles<br> $x<br><br> };
}}
}
$stopwatch_uit=(times)[0];
print qq{<hr>};
printf "search time: %.8f seconds\n",$stopwatch_uit- $stopwatch _aan;
Then they are read out again and each record will be checked if
a value of the array @words is present, if so the
record will be printed.
The problem is that the 'foreach $x (@words){' line doesn't go through
each character/word of @words. I tried it with the parameter sentence 'hello,0,c'.
When I trie to print out the $x value it gives me the value 0 instead of the
current value of @words.
- How can I fix this problem ?
- Also I must make this script faster (the part between the stopwatch lines)
So I hope someone can alter this script to produce faster output.
#!/usr/bin/perl
use CGI;
use DB_File ;
$q=new CGI;
print "Content-type: text/html\n\n";
$sentence=$q->param('sente
@words=split(",",$sentence
unlink "fruit" ;
tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open file 'fruit': $!\n";
for ($xx=1; $xx<100; $xx++){
$h{$xx} = 'CIS100@é@01@é@Intro@é@to Computing@é@8';
}untie %h ;
$stopwatch_aan=(times)[0];
tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open file 'fruit': $!\n";
while (($h,$line)=each %h){
@line=split('@é@',$line);
foreach $x (@words){
if (grep /$x/,@line){
($Course,$Section,$Title,$
print qq{Record=$h<br>Course=$Co
}}
}
$stopwatch_uit=(times)[0];
print qq{<hr>};
printf "search time: %.8f seconds\n",$stopwatch_uit-
First of all, the foreach should work. Are you sure you passed "hello,0,c" correctly? Another thing is did you notice you mixed @line and $line?
A couple suggestions to speed up:
1. Instead of @words = split(/,/, $sentence), you should do $sentence =~ s/,/\|/g; Then get rid of foreach, instead use grep /$sentence/, @line That'd definitely be faster.
2. For last files, get rid of tie, foreach, grep altogether and instead use open(IN, "grep $sentence fruit |"), that'll definitely be faster for larger files.
A couple suggestions to speed up:
1. Instead of @words = split(/,/, $sentence), you should do $sentence =~ s/,/\|/g; Then get rid of foreach, instead use grep /$sentence/, @line That'd definitely be faster.
2. For last files, get rid of tie, foreach, grep altogether and instead use open(IN, "grep $sentence fruit |"), that'll definitely be faster for larger files.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thank you so far. I'll take a look at your comment and give away the points later this week.
ASKER
inq123
Can you give me an example (some code) based on my script with the line:
open(IN, "grep $sentence fruit |")
in it ?
Can you give me an example (some code) based on my script with the line:
open(IN, "grep $sentence fruit |")
in it ?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
inq123
The first two scripts work perfectly, though the second script takes about 8 seconds to complete (using perlwiz on a pentium 3 655 mhz.)
When I try to test the third script I receive the following error:
Insecure $ENV{PATH} while running -T switch at line 11
(line 11= the open(IN, "egrep '$sentence' fruit |"); )
What is wrong with that line ?
Fishmonger, still among us ?
The first two scripts work perfectly, though the second script takes about 8 seconds to complete (using perlwiz on a pentium 3 655 mhz.)
When I try to test the third script I receive the following error:
Insecure $ENV{PATH} while running -T switch at line 11
(line 11= the open(IN, "egrep '$sentence' fruit |"); )
What is wrong with that line ?
Fishmonger, still among us ?
YES, I'm still here but I've been side tracked in multiple directions. Tomarrow, when my head clears of the all the alcohol that I've drank, I'll see what input I can give.
ASKER
;)) ok, thanks
When running the scipt under taint mode, Perl keeps track of data that comes from the user (or external command) to avoid doing anything insecure with it. In this case, you're inheriting $ENV{PATH} and calling an external program (egrep) which Perl's taint mode says is insecure. You could add a couple of lines at the beginning of the script which will allow you to run the script in a more secure environment.
$ENV{PATH} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV'};
$ENV{PATH} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV'};
If you need/want more detailed info on the use and effects of Perls taint mode, I'd recommend 'CGI Programming with Perl' by Scott Guelich, Shishir Gundavaram & Gunther Birznieks and/or 'Programming Perl' by Larry Wall, Tom Christiansen, & Jon Orwant.
ASKER
Ok, thank you all for contributing. I'll close the question. I'm gonna use the second script inq123 gave me.
each character/word of @words. I tried it with the parameter sentence 'hello,0,c'.
When I trie to print out the $x value it gives me the value 0 instead of the
current value of @words.
==> well, actually it does.
foreach $x (@words) {
print "\$x=$x\n"; #<=== insert this to verify
if (grep /$x/,@line){
...
Also, why use grep and not plain m//?
hec",)