When I write out a HTML::Table I want to skip certain rows. This should be done according to a few user parameters which I get from the web page and compile them as regex.
The Parameters are the upper case NOT_* with values such as cc08 or a post code or whatever.
my $nameRegex = ($NOT_NAME) ? qr/$NOT_NAME/ : '';
my $rackRegex = ($NOT_RACK) ? qr/$NOT_RACK/ : '';
my $unitRegex = ($NOT_UNIT) ? qr/$NOT_UNIT/ : '';
my $addressRegex = ($NOT_ADDR) ? qr/$NOT_ADDR/ : '';
my $townRegex = ($NOT_TOWN) ? qr/$NOT_TOWN/ : '';
my $pcodeRegex = ($NOT_PCODE) ? qr/$NOT_PCODE/ : '';
In the while loop (for a SQL query elsewhere) I get the data, and what I think im doing is “unless you match any of these” add this row of results.
while ((my $id, my $name, my $rack, my $unit, my $town, my $address, my $pcode, my $lat, my $lon) = $select_sites->fetchrow_array()) {
my $checkbox = "<input type='checkbox' name='FILTER_SITE' value='$id' $checked{$id} />";
unless ($name =~ $nameRegex
|| $rack =~ $rackRegex
|| $unit =~ $unitRegex
|| $address =~ $addressRegex
|| $town =~ $townRegex
|| $pcode =~ $pcodeRegex) {
$rows++;
$sitesResultSection->addRow($checkbox, $name, $rack, $unit, $town, $address, $pcode, $lat, $lon);
}
Spitting the Regexs would look something like this for $NOT_RACK = "cc08"
= qr//;
(?-xism:cc08) = qr/cc08/;
= qr//;
= qr//;
= qr//;
= qr//;
However the problem is no rows are added at all, while only one result in the query must be omitted for “cc08”, and all others must be shown.
The reason I’m doing this in HTML is because there are already other filters in the SQL query (limiting the result set significantly) and making those filters dynamic according to user input would be a nightmare.
Answer accepted, however I had a further issue:
This is how I initialised those NOT_s, in the same fashion I used for my query’s REGEXP conditions. Thusly when a user enters “City rackname” it’ll display racks in City
my $NOT_NAME = &useOrs(&trim($cgi->param('NOT_NAME')));
my $NOT_RACK = &useOrs(&trim($cgi->param('NOT_RACK')));
my $NOT_UNIT = &useOrs(&trim($cgi->param('NOT_UNIT')));
my $NOT_ADDR = &useOrs(&trim($cgi->param('NOT_ADDR')));
my $NOT_TOWN = &useOrs(&trim($cgi->param('NOT_TOWN')));
my $NOT_PCODE= &useOrs(&trim($cgi->param('NOT_PCODE')));
my $QUICK_SEARCH_SITES = &trim($cgi->param('QUICK_SEARCH_SITES'));
my $searchRegexp = ($QUICK_SEARCH_SITES) ? &useOrs($QUICK_SEARCH_SITES) : '.*';
sub useOrs {
my $tmp = $_[0];
$tmp =~ s/\s+/|/g;
return $tmp;
}
Here’s an excerpt from the SQL query WHERE name REGEXP ? OR rack-id REGEXP ? OR [..]
So with these hacks some reasonable flexibility is achieved without having to train the monkeys that will use the tool.
However using merely $var =~ /$NOT_VAR/ will apparently match only exactly that, case sensitive etc.
To achieve the looseness of the SQL filter Instead of using &useOrs I use
sub useAny {
my $tmp = $_[0];
$tmp =~ s/\s/./g;
return $tmp;
}
And most importantly $var =~ /.*$NOT_VAR.*/i
I was under the impression that one is supposed to hack away with Perl so there.. 🙂 Suggestions still welcome.
Update:
As Sinan Ünür has pointed out, there is a hidden functionality, described in perlop in that any empty regex
//will instead use the last successfully matched regex. A very strange feature, IMO, and in this case will cause subtle errors.That makes it a bad idea to use variables inside regexes, unless they are checked for content first.
Solution:
What you should do, IMO, is exchange this for a subroutine, e.g.:
And then use it as such: