当我写出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
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劈开那么那里...... :)建议仍然欢迎。
答案 0 :(得分:4)
空模式
//
如果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)}
}
}
这假设列名与您使用的变量名匹配。
最后,您在SQL where
中使用select
子句吗?如果可以的话,最好指定在获取数据之前应排除哪些行。
例如,select name, rack, unit, address, town, pcode lat lon from TABLE where rack <> 'cc08' and town <> 'Concord'
或其他内容。
答案 1 :(得分:1)
更新:
正如SinanÜnür所指出的那样,perlop中描述了隐藏的功能,任何空的正则表达式//
都将使用最后一个成功匹配的正则表达式。一个非常奇怪的功能,IMO,在这种情况下会导致细微的错误。
这使得在regex中使用变量是个坏主意,除非先检查它们的内容。
<强>解决方案:强>
你应该做什么,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)
....