I have been racking my brain trying to figure this out for 3 days and I can't get it. I hate asking for help or questions but my need for this to work is greater. :-)
I have a perl script that edits a flat file that I want to add the functionality of sorting by field name by 123 or 321 or abc or cba. The url would look like this.
...com/admin.pl?order=FieldName&order_by=321
You probably would need the whole Perl code let me know but this is the snippet I'm trying to use:
$order = "ORDER BY ID ";
if($FORM{order}){
for (@show_fields){
if($_ eq $FORM{order}){
$order = "ORDER BY $FORM{order} ";
$order.= $FORM{order_by} eq '321'? "DESC":"";
last;
}
}
}
Your question does not make a lot of sense, which is probably why you're not sure what to do.
I have a perl script that edits a flat file that I want to add the functionality of sorting by field name
OK so far, but what does this mean?
by 123 or 321 or abc or cba.
You say you want to sort a 'flat file', but ORDER BY ID would indicate that you are using a database.
Post a line or two of the flat file and explain what you are trying to order by.
Are you trying to order the content of the flat file by a 'field name', or are you trying to order the content of the 'field name'?
And you really should be using 'strict' and the CGI.pm module.
OK!
I'm pretty sure you mean sort by a field in ASCENDING or DESCENDING order
I would use
admin.pl?order=0 - for ascending, default (abc,123)
admin.pl?order=0&desc=1 - for descending (cba,321)
The order value will be 0-color, 1-name, 2-sex, 3-id
If you have a small file, say less that 50k records, I would read the whole thing into a hash where the hash key is the sort field. Now sort the keys in ascending or decending order and write the data into a temp file. rename the old file .bak. and rename the temp file.
Might look something like this
Code:
my $order = $FORM{order}; ## better to use the CGI.pm module
my $desc = $FORM{desc} || 0;
#open file to read
my %hash;
while (<FIL>) {
my @line = split(/|/);
$hash{@line[$order]} = $_;
}
#close file
my @hashkeys = keys %hash;
if ($desc) { sort {$b cmp $a} @hashkeys; } else { sort @hashkeys; }
#open temp file to write
for (@hashkeys) {
print TMP $hash{$_};
}
#close file
Nedals do I need to append the code below into my Sub Read portion of the script. Also I'm not sure excatly what you mean by saving a back up of my database file and renaming it. When I do a sort it must pull from the "live" database for real time data. Not sure what that snippet actually does.
I suggest you put "use strict;" at the top of your script. It will catch more errors, require you to declare variables (fixing scope issues), etc. At the beginning of the script you attached, you declare an array data to be based on the sub order, but inside order you use data before it's been initialized! Unless it's initialized in code you didn't include, it could cause you trouble.
You may want to try turning your @data array into an associative array. This is what I do when I am reading in such files. If you don't understand it, either try to figure it out or don't use it; I haven't tested it. Skip to below the code.
my $data = {}; # a reference to an associative array
my @keys = ();
my $row = 0;
#loop through lines in the file
while (<FILE>) {
chomp();
if ($row == 0) {
# legend row
@keys = split("|", $_);
} else {
# data row
my $row = {};
my @values = split("|", $_);
# loop through items between the pipes
for (my $i = 0; $i < scalar(@values); $i++) {
$row->{$keys[$i]} = $values[$i];
}
$data->{$values[0]} = $row;
}
}
# now you have a hash
# $data with keys being the first element of each row
# and values being another hash
# with keys being the legend on the first row.
# NOW you should be able to use grep, map, & sort with
# fewer "for" loops.
Are you familiar with hashes (associative arrays) and the commands "grep" and "map"?
If not, you will appreciate how smooth they make your script. It will also help in that you'll have fewer loops with if statements tucked inside - and fewer bugs. But you MUST understand how they work before you use them.
First, grep. Grep will pull out exactly what you want from an array, based on the conditional inside brackets. This conditional can be more than one statement but must return a value; 0 means don't include it, more than 0 means include it.
The following will return an array containing any elements from @show_fields that equal $FORM{order}.
my @array = grep { $_ eq $FORM{order} } @show_fields;
Next, map. Map will turn an array into a different array based on the return value from the subroutine within brackets.
my @array2 = map { "ORDER BY $_" } @array;
Done correctly, this will return an array of one element containing the string you want. Code follows, but I combined the grep & map. I did test this snippet alone and it worked.
$order="ORDER BY ID ";
if ($FORM{order}) {
$order = (map { "ORDER BY $_" } grep { $_ eq $FORM{order} }
@show_fields)[0];
}
If it doesn't work for you, I suggest you check the rest of your code.
Perhaps I should not have responded to this thread. I do not have the time to work with you on incorporating this code into your script. Hopefully someone else can be of help. (that's why i'm posting this)
I don't know where this snippet of code will fit into your overall script. All it does is to take data that is read from a file and sorts it based on a specified field either in ascending or descending order. What you do with the resulting data is entirely up to you.
...I have a perl script that edits a flat file...
How do you currently handle your edited data? You probably need to do something similar with the sorted data.
NOTE: I don't even know if this snippet works. It's just an idea to give you a way of thinking.
Thanks Nedals for your suggestions, and thanks Mary for the code and a little tutorial. I do appreciate it!
However when inserting the code it did nothing. I don't get a cgi error nor does the script act any differently. I will continue to try different variations here.
I think your bug is deeper in the code. To search for it, comment out most of your program but leave a little bit. Make sure that little bit works (using print statements), then uncomment some more code. Go on and on until you know everything works. It's tedious, but a great way to verify that the other parts of your code work. And it's not something that anyone but you can do- it's your program!
Bookmarks