PDA

View Full Version : PERL help


mewmew
10-01-2002, 10:03 AM
Hello. I've developed a large portion of my site now but there's a few things I've skipped making during it (due to lack of perl knowledge :) ) so now I'm going back through them and trying to fill in the gaps. Here's my first problem;

I'm making a page (.shtml, in perl/cgi) so users can request what they want simply by typing it in the input box and posting it, then have it sent to a script that checks if it's a new entry, updates the count for it if not, or creates the new entry if so. Then I need to display them on the page in order of most to least popular. I doubt there's any scripts around for this so I'm trying to learn how to code it. (easier said than done for me). I'm really stuck on how to go about doing this. I know I'll need to use an array but I don't have much experience with them. I'm trying to set it out as;

$keyword=$FORM{keyword};
$logfile="log/requests.txt";
$found="1";
open(FILE,">$logfile");
read file
put in array
foreach in array {
if current value eq $keyword {
get count for value
$value++
print 'over write place in file with new data'
$found++
}
}
if ($found eq 2) {
print 'add to file in place'
}
close(FILE);

print "Content-type: text/html\n\n";

print 'first of top ten'
etc..


I think that's roughly how I'd set it out. Can anyone show me how I'd write it? :(

kevin
10-01-2002, 01:38 PM
I would like to see the website you will be using this code on before posting a reply.

mewmew
10-01-2002, 05:47 PM
Hi.

kevin: I'm not publishing my website 'til it's complete as I'm yet to do any .htaccess and as such have a lot of security holes (mainly in news posts/forums). I can send you the page I'm creating though if it would help, or offer more information if it's needed. I'm using a post method to submit the requests, on a unix server, coming from my request.shtml page (which uses action=request.cgi) etc. I'm a little puzzled as to what info needed for this, I haven't given, though.

kevin
10-01-2002, 06:07 PM
OK.... what is the general concept of the website? Sounds like you want some sort of a ranking system, plenty of scripts that already do that.

mewmew
10-02-2002, 05:31 AM
It's for a game FAQ site, I'll need this page so people can request which FAQ's they would like created in future (I'm trying to make my site as interactive as possible). So when the users go to my site i can have the top 10 most requested on it, so the authors have a better idea what to work on etc. Thanks for responding by the way kevin

mewmew
10-02-2002, 11:37 AM
I have had a shot at this (at least the first part anyway) and I came up with this:



$keyword=$FORM{keyword};
$logfile = "logs/test.txt";
$match = "1";
&build;

sub build {

print "Content-type: text/html\n\n";
open(FILE,"<$logfile");
@LINES = <FILE>;
close(FILE);
open(FILE,">$logfile");
foreach $LINE (@LINES) {
($word,$count) = split(/[:]/,$LINE);

if ($keyword eq $word) {
$count++;
$match++;
print FILE join(":", ($word, $count)), "\n";
}

else {
print FILE join(":", ($word, $count)), "\n";
}

}

unless ($match eq 2) {
$count = "1";
print FILE join(":", ($keyword, $count)), "\n";
}

close(FILE);

# This is just so I can see how it outputs after
open(FILE,"$logfile");
@LINES = <FILE>;
close(FILE);
foreach $LINE (@LINES) {
print "$LINE<br>";
}

}



It worked till I changed it so it adds a new entry. Then it just gets messed up (the \n's are responsible, i think). I get something like;

entry:1
entry2:0

Then when I add another entry that exists (e.g entry2):

entry:1
entry2:1

Then when I add a unique entry:

entry:1
entry2:1

entry3:1



(I'm still learning) Where am I going wrong?

kevin
10-02-2002, 01:40 PM
OK....hard to tell just what you are trying to do by looking at your code but see if this works better (untested), you should be able to tell the difference just by looking at the code:


$keyword=$FORM{keyword};
$logfile = "logs/test.txt";
$match = 0;
&build;

sub build {

print "Content-type: text/html\n\n";
open(FILE,"<$logfile");
@LINES = <FILE>;
close(FILE);
open(FILE,">$logfile");
for $line (@LINES) {
chomp $line; #removes \n from end of line
($word,$count) = split(/:/,$line);
($count++,$match++) if ($keyword eq $word); # only increment on a word match
print FILE join(":", ($word, $count)), "\n";
}
print FILE "$keyword:0\n" if ($match == 0);
close(FILE);

# This is just so I can see how it outputs after
open(FILE,"$logfile");
@LINES = <FILE>;
close(FILE);
foreach $LINE (@LINES) {
print "$LINE<br>";
}
}

mewmew
10-02-2002, 05:39 PM
Thanks a lot kevin, you're a big help. And yes, I do see a big difference lol Your code is much neater (and it actually works). I think the big thing I needed to learn there was the chomp command and to organise it better. Once again thanks for your help :)

mewmew
10-03-2002, 08:15 AM
May as well ask my last q here rather than start a new topic. Now I know how to store the entry, how would I organise the file so the highest entry are at the top? I think I know how I could do it using foreach if ($value > $value) etc but I'd have to cycle it a few times over before it was all organised (the way I can think of anyway) and it'd go extremely slow with a heap of entry/lot of users. How can I go about doing this?

ishnid
10-03-2002, 11:00 AM
It's easy using the Sort::Fields module...

use Sort::Fields;
@sorted = fieldsort ':', ['2n'], @LINES;

mewmew
10-03-2002, 11:25 AM
Do you know what version of perl the module's available on? It doesn't seem to load for me (using 4.x).

It'd be a lot easier that way but it looks like I'll need to code it.

mewmew
10-04-2002, 05:29 AM
Doubt anyone'll ever answer this now :crying:

ishnid
10-04-2002, 06:27 AM
You can get it from cpan: http://search.cpan.org/author/JNH/Sort-Fields-0.90/

mewmew
10-04-2002, 10:13 AM
Thanks for taking the time out to help ishnid. I did have a look at the module but I'm clueless on how to install it (as far as I could see there was no info on it in the .zip/site). I'm not sure if you have to install it on the webhost (which I don't have access to) or if you can just run it off your site, which I did try actually but without success. Would it require a lot of code to do this without using modules? This is really frustrating because it's near enough the last thing I need to learn to finish my site and I just can't work out how to go about doing it.

kevin
10-04-2002, 12:51 PM
if ishnids suggestion will not work for you , try this untested code and see if it will, its using a rather inefficient sort method but if the file is not a really long file with thousands of keywords to cycle through it should work OK.


$keyword=$FORM{keyword};
$logfile = "logs/test.txt";
$match = 0;
&build;

sub build {

print "Content-type: text/html\n\n";
open(FILE,"<$logfile");
@LINES = <FILE>;
close(FILE);

for $line (@LINES) {
chomp $line; #removes \n from end of line
($word,$count) = split(/:/,$line);
($count++,$match++) if ($keyword eq $word); # only increment on a word match
$line = join(':', $word,$count);
}
@LINESNEW = sort {($b =~ /:(\d+)$/)<=>($a =~ /:(\d+)$/)} @LINES;

open(FILE,">$logfile");
foreach(@LINESNEW){
print FILE "$_\n";
}
print FILE "$keyword:0\n" if ($match == 0);
close(FILE);

# This is just so I can see how it outputs after
open(FILE,"$logfile");
@LINES = <FILE>;
close(FILE);
foreach $LINE (@LINES) {
print "$LINE<br>";
}
}

mewmew
10-04-2002, 02:12 PM
hi kevin. I'm thinking this is a curse or something, it outputted in the exact same format. I don't usually give up but I'm getting close to it lol I did ask elsewhere about this problem too and they came up with this;

sub SortFile{
my @data;
#file locking doesn't work on Windows and may cause fatal errors.
# If you want it, set to "Y"
my $filelock = "N";
# set this to the name of your txt file
my $sortthis = "somefile.txt";
open (SORTFILE,"$sortthis") || die"Cant open database\n";

for(<SORTFILE> ){
my @fields = split/\:/;
unshift @data, \@fields;
}
close(SORTFILE);
my @sorted = sort {($b->[1]) <=> ($a->[1])} @data;
for(@sorted){
my @fields = @$_;

my $line = join(":", @fields[0..1]);
if($line ne ""){
push(@myArray,$line);
}
}

### now we're sorted so write it back to the file

open(FILE2,">$sortthis") || print "$!";
if($filelock eq "Y"){flock (FILE2, 2)}
print FILE2 @myArray;
if($filelock eq "Y"){flock (FILE2, 8)}
close (FILE2);
}


which also didn't work. I couldn't see anything wrong with this code either (unless there's a 'my' missing anywhere?) I don't know. It's a shame about this because if I can't get it working I'll have to filter the file myself, an with a large user base it'd take ages. O well, thanks to anyone who helped.

kevin
10-04-2002, 02:32 PM
I think I made a little boo-boo in my code. Change this line:


@LINESNEW = sort {($b =~ /:(\d+)$/)<=>($a =~ /:(\d+)$/)} @LINES;



to this:


@LINESNEW = sort {($b =~ /:(\d+)$/)[0]<=>($a =~ /:(\d+)$/)[0]} @LINES;


and see if it helps.

mewmew
10-04-2002, 02:53 PM
woo, there is a god! kevin be thy name :) thank you again, again! lol you're a website life saver. hopefully I'll start to help other people out here soon too. *gets back to work* thanks again!