2012-05-01 4 views
0

HTML::Tableを書き出すときに、特定の行をスキップしたいとします。これは、私がWebページから取得し、それらを正規表現としてコンパイルするいくつかのユーザパラメータに従って行う必要があります。Perlでは、複数の正規表現マッチを使用してDBI selectから返されたいくつかの行をスキップできますか?

パラメータは、大文字のNOT_*です(cc08などの値または郵便番号など)。 (他の場所でSQLクエリ用)whileループで

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

私は、データを取得し、その結果、この行を追加し、「あなたはこれらのいずれにも一致しない限り、」私はイムがやって考えることです。

クエリ内の1つの結果だけが「cc08」のために省略されている必要がありながら、 $NOT_RACK = "cc08"

= qr//; 
(?-xism:cc08) = qr/cc08/; 
    = qr//; 
    = qr//; 
    = qr//; 
    = qr//; 
問題は行がすべてに追加されていないですが

ために、次のようになりRegexs唾吐き

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

、その他はすべて表示する必要があります。

私はこれをHTMLでやっているのは、SQLクエリに他のフィルタがあり(結果セットが大幅に制限されている)、ユーザ入力に応じてこれらのフィルタを動的にすることが悪夢になるからです。これは私が私が私のクエリのREGEXP条件に使用したのと同じやり方で、それらのNOT_sを初期化する方法である

回答を受け入れ、しかし、私はさらに問題がありました。ユーザーが入力Thuslyたときに「市のracknameは、」それはここでは、SQLクエリからの抜粋です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; 
} 

にラックを表示しますWHERE name REGEXP ? OR rack-id REGEXP ? OR [..] だから、いくつかの合理的な柔軟性が使用するサルを訓練することなく達成され、これらのハックとツール。 は、しかし、私は下にあった

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

そして、最も重要な$var =~ /.*$NOT_VAR.*/i

を使用する代わりに&useOrsを使用してのSQLフィルターの緩みを達成するために、単に$var =~ /$NOT_VAR/は明らかにのみ正確に一致します大文字と小文字の区別など を使用して印象的なのは、Perlでハックすることになっているという印象。:)まだ提案は大歓迎です。

+0

別の質問がある場合は、別の質問を投稿してください。 * 1つはPerlでハックすることになっています*はうまく反映されません。プログラミング言語が何であれ、壁に物を投げつけるまでしばらくの間、物事を投げるのは正しいアプローチではありません。 –

+0

自分のコードでさらに問題が発見されたため、私は投稿を拡大していません。ハッキングは問題を正しく解決するはずですか?私は現在受け入れられている解決策が適切かつ堅牢で読みやすいと感じています – Recct

+1

'/.* ...。* /'はperl正規表現のデフォルトの動作であり、追加する必要はありません。 '/ $ NOT_VAR /'は '/.*$ NOT_VAR。* /'とまったく同じものにマッチします。何かをキャプチャしている場合や '/ g'オプションを使用している場合にのみ重要です。あなたはそうではありません。 – TLP

答えて

1

更新:シナンÜnürが指摘したように

、隠された機能があり、任意の空の正規表現//ではなく、最後に正常にマッチした正規表現を使用することでperlopで説明。非常に奇妙な機能、IMO、およびこの場合、微妙なエラーが発生します。

これは、コンテンツが最初にチェックされていない限り、正規表現内の変数を使用することをお勧めしません。

ソリューション:

あなたが、IMO、サブルーチンのためにこれを交換している何をすべきか、例えば:

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

そして、そのように使用します。perldoc perlopから

unless (check_var($name, $NOT_NAME) 
     || check_var($rack, $NOT_RACK) 
     .... 
+0

さて、すべての結果が表示され、NOTがまったく適用されないようです。 – Recct

+0

@Reccここでif条件に関して話すなら、非常に役立ちます。 「すべての結果が表示されています」と言うと、コードを確認する必要があります。私は 'unless'ブロックの中にあるものが実行されるということを意味すると思います。これは、少なくとも1つの 'check_var'呼び出しがすべての行に対してtrueを返したことを意味します。理由を理解する必要があります。そのためには、Data :: Dumperモジュールを使用してデータの内容を確認することが最善の方法です。 '$ Data :: Dumper :: Useqq = 1;を試してください。 print Dumper $ NOT_NAME; 'など。空白は" true "とカウントされます。 – TLP

+0

実際、変数については何も起こっていませんでしたが、それは私が見落としたことでしたが、MySQLの正規表現とPerlの処理の違いと私の目には私の答えで明らかになるでしょう空の '//'が最初の壁であったほど深くなりました。この回答は現在最も適しており、素晴らしいです。 – Recct

4

空のパターン//

パターンは、空の文字列に最後に評価された場合 成功 m代わりに慣れた正規表現が使用されます。 この場合、空のパターンの "g"と "c"フラグだけが となります。他のフラグは元のパターンから取得されます。 以前に成功した一致がない場合、これは(黙って) を真の空のパターンとして実行します(常に一致します)。

だから、あなたが使用することによってあなたの人生を容易にすることができます。これは、列を想定してい

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

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

または、より良いが、ハッシュを(コードはをテストされていません)を使用名前は使用した変数名と一致します。

最後に、selectwhere句を使用していますか?可能であれば、データを取得する前にどの行を除外すべきかを指定する方がはるかに優れています。

たとえば、select name, rack, unit, address, town, pcode lat lon from TABLE where rack <> 'cc08' and town <> 'Concord'またはその行に沿ったものです。

+0

+1変数が同じでなくても、最後に成功した正規表現を使用するのは真実です。私はこれまでにそれについて聞いたことがないし、ちょっと変わっているようだ...多くの奇妙で難しいバグを見つけるための情報源です。 – TLP

+1

ハッシュディスパッチ+1。私はときどき人々がある種の危険なパターンを構築しているのを見ています: '$ r = join '|' => grep {length} @runtime_patterns; qr/$ r/if $ r'となる。 FWIWでは、[List :: MoreUtils](http://search.cpan.org/perldoc?List::MoreUtils)の 'any()'はスカラーgrepよりも効率的です。 – pilcrow

+1

@pilcrow 'any'を提案してくれてありがとう。忘れてた。より重要なのは、効率よりも、表現力が豊かになります。 –

関連する問題