0

当我写出 a 时,HTML::Table我想跳过某些行。这应该根据我从网页获得的一些用户参数来完成,并将它们编译为正则表达式。

参数是大写的NOT_*,带有诸如cc08邮政编码之类的值。

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/ : '';

在while循环中(对于其他地方的SQL查询)我得到数据,我认为我正在做的是“除非你匹配其中任何一个”添加这行结果。

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);
        }

吐出正则表达式看起来像这样$NOT_RACK = "cc08"

  = qr//;
 (?-xism:cc08) = qr/cc08/;
  = qr//;
  = qr//; 
   = qr//;
  = qr//;

但是问题是根本没有添加任何行,而“cc08”必须省略查询中的一个结果,并且必须显示所有其他结果。

我在 HTML 中这样做的原因是因为 SQL 查询中已经有其他过滤器(显着限制了结果集),并且根据用户输入使这些过滤器动态化将是一场噩梦。

接受了答案,但是我还有一个问题:

这就是我初始化那些 NOT_s 的方式,与我用于查询REGEXP条件的方式相同。因此,当用户输入“City rackname”时,它会在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;
}

这是 SQL 查询的摘录WHERE name REGEXP ? OR rack-id REGEXP ? OR [..] 因此,通过这些技巧可以实现一些合理的灵活性,而无需训练将使用该工具的猴子。但是,仅使用$var =~ /$NOT_VAR/显然只会完全匹配,区分大小写等。为了实现 SQL 过滤器的松散性,而不是使用&useOrs我使用

sub useAny {
    my $tmp = $_[0];
    $tmp =~ s/\s/./g;
    return $tmp;
}

而且最重要的是$var =~ /.*$NOT_VAR.*/i

我的印象是应该用 Perl 破解所以那里.. :) 仍然欢迎提出建议。

4

2 回答 2

4

perldoc perlop

空的图案//

如果 PATTERN 计算结果为空字符串,则使用最后 成功匹配的正则表达式。在这种情况下,只有空模式上的“g”和“c”标志被接受;其他标志取自原始模式。如果之前没有匹配成功,这将(默默地)充当真正的空模式(它将始终匹配)。

因此,您可以通过以下方式让您的生活更轻松:

my $nameRegex = qr/$NOT_NAME/;
my $rackRegex = qr/$NOT_RACK/;
my $unitRegex = qr/$NOT_UNIT/;
my $addressRegex = qr/$NOT_ADDR/; 
my $townRegex  = qr/$NOT_TOWN/;
my $pcodeRegex = qr/$NOT_PCODE/;

或者,更好的是,使用哈希(代码未经测试):

use List::MoreUtils qw( any );

my %patterns = (
    name => qr/$NOT_NAME/,
    rack => qr/$NOT_RACK/,
    unit => qr/$NOT_UNIT/,
    address => qr/$NOT_ADDR/,
    town => qr/$NOT_TOWN/,
    pcode => qr/$NOT_PCODE/,
);

while (my $row = $select_sites->fetchrow_hashref("NAME_lc")) {
    my $checkbox = '...';

    next if any { $row->{$_} =~ $patterns{$_} } keys %patterns;

    $rows++;
    $sitesResultSection->addRow(
        $checkbox,
        @{ $row }{qw(name rack unit town address pcode lat lon)}
    }
}

这假定列名与您使用的变量名匹配。

最后,您是否where在 SQL 中使用了子句select?如果可以的话,最好在获取数据之前指定应排除哪些行。

例如,select name, rack, unit, address, town, pcode lat lon from TABLE where rack <> 'cc08' and town <> 'Concord'或类似的东西。

于 2012-05-01T16:42:41.757 回答
1

更新:

正如 Sinan Ünür 所指出的,有一个隐藏的功能,在perlop中描述,任何空的正则表达式//都将使用最后一个成功匹配的正则表达式。一个非常奇怪的功能,IMO,在这种情况下会导致细微的错误。

这使得在正则表达式中使用变量是一个坏主意,除非首先检查它们的内容。

解决方案:

IMO,您应该做的是将其交换为子例程,例如:

sub check_var {
    my ($var, $NOT_VAR) = @_;
    return 0 unless $NOT_VAR;
    return ($var =~ /$NOT_VAR/);
}

然后像这样使用它:

unless ( check_var($name, $NOT_NAME) 
      || check_var($rack, $NOT_RACK)
      ....
于 2012-05-01T16:35:09.497 回答