0

私のデータファイル:votes.txtは、次と同じ行で構成されています。

VOTE 1168241980 Campaign:ssss_uk_01B Validity:during 
Choice:Tupele CONN:MIG00VU MSISDN:00088866655598 
GUID:A34-FDS87-FHDHDH-DHDHDHD0 Shortcode:63334

各エントリはスペースで区切られています。現在、19行のサンプルがあります。

田畑:

CONN:MIG00VU MSISDN:00088866655598 
GUID:A34-FDS87-FHDHDH-DHDHDHD0 Shortcode:63334

この演習には使用されていません。

#!/usr/bin/perl 

use warnings;
use strict;
use Switch;
use DBI();

#
# _voting.pl
#

# Connect to the database.
my $dbh = DBI->connect("DBI:mysql:database=sms_voting;host=localhost",
                    "sisisi", "*********",
                    {'RaiseError' => 1});

my $sth = $dbh->prepare("INSERT INTO voting 
(epoch, validity, choice, campaigns_id, candidates_id ) VALUES (?,?,?,?,?)");

open (LOGFILE, '/var/www/voting/votes.txt') or die("Could not open log file.");

my $errors = 0;
my $campaign_id = 0;
my $candidate_id = 0;

foreach my $line (<LOGFILE>) {  

    my ($vote, $epoch, $campaign, $validity, 
 $choice, $CONN, $MSISDN, $GUID, $Shortcode) = split(' ', $line);

# parse the field:value entries...
$campaign = substr $campaign, 8, 11, '';
$validity = substr $validity, 9, 6, ''; # during
$choice = substr $choice, 7, 10, ''; # Brown

# case statements to define correct foreign keys...
 switch ($campaign) {
        case ("ssss_uk_01B")    { $campaign_id = 1 } 
        case ("ssss_uk_01C")    { $campaign_id = 2 } 
        case ("ssss_uk_01D")    { $campaign_id = 3 } 
        case ("ssss_uk_01E")    { $campaign_id = 4 } 
        case ("ssss_uk_01F")    { $campaign_id = 5 } 
        case ("ssss_uk_01G")    { $campaign_id = 6 } 
}

switch ($choice) {
        case ("Brown")      { $candidate_id = 1 } 
        case ("Cameron")    { $candidate_id = 2 } 
        case ("Balls")      { $candidate_id = 3 } 
        case ("Green")      { $candidate_id = 4 } 
        case ("Boring")     { $candidate_id = 5 } 
        case ("Tupele")     { $candidate_id = 6 } 
}

if ($epoch && $validity && $choice && $campaign_id && $candidate_id ) {

    $sth->execute($epoch, $validity, $choice, $campaign_id, $candidate_id);
    # debug
    print "$epoch $validity $choice \n"; # 1161048980 during Green
    next;
} 

$errors++;
 }

close (LOGFILE);

# debug
print qq(errors=$errors\n);

foreachのループごとに、$campaign変数と$choice変数がswitchステートメントを介して実行され、candidate_idとcampaign_idの番号が定義されます。これらの外部キーは、候補とキャンペーンテーブルまたはキャンペーンテーブルにマップされます。

データベースモデルについては、 http ://acookson.org/wp-content/themes/cookie_23112012/img/sms_voting.pngを参照してください。

すなわち

INSERT INTO voting (epoch, validity, choice, campaigns_id, candidates_id ) 
VALUES (1161048980,'during','Brown', 1, 1),
(1161048980,'during','Tupele', 3, 5), ... etc

投票.txtでnull値が検出されると、$errors変数がインクリメントされます。

スクリプトはvotes.txtを正常にループしているように見えますが、初期化に失敗しています:$campaign_idおよび$candidate_id変数または。完了すると、errors=19が端末に出力されます。サンプルデータvotes.txtの行の総数。つまり、このファイルのすべての行をデータベースに挿入できませんでした。

mysql> select * from voting;
Empty set (0.00 sec)

これを確認します。

スクリプトは構文エラーを報告しません。したがって、それはより低いレベルです。スイッチがなくても正常に動作します。したがって、それはそれをいくらか絞り込んだ。スイッチの問題はわかりませんが、ここでアドバイスを探しています。

4

2 に答える 2

0

問題が何であるかはわかりませんが、Switchステートメントやその他のコードに関するいくつかの指針があります。

私の知る限り、use Switch機能/モジュールはperl v5.10.1で機能に置き換えられ、given/when現在は非推奨になっています。個人的に、私はいつもこれらのステートメントが少し奇妙で信頼できないことに気づきました。そして、perlは非常に柔軟な言語であるため、決してかけがえのないものではありません。

あなたの場合、代わりにハッシュルックアップをお勧めします:

my %camp = ("ssss_uk_01B" => 1,
            "ssss_uk_01C" => 2,
            ...);
my %cand = ("Brown"       => 1,
            "Cameron"     => 2,
            ...);

$campaign_id  = $camp{$campaign};
$candidate_id = $cand{$choice}

デフォルト値を指定する必要がある場合は、defined-or代入演算子を使用できます。

$campaign_id //= "default value here";

あなたのsubstr割り当ては少し間違っています。まず、4つの引数すべてを使用します。これは、perldocでは次のように記述されています。

substr EXPR,OFFSET,LENGTH,REPLACEMENT

これは、一致を''空の文字列に置き換えることを意味します。これは変数自体に影響し、そのままにしておくと必要なデータが削除されます。あなたの場合の長さも、あなたが後にしている文字列の終わりなので、必要ありません。substr最後に、ステートメントの戻り値を使用するという事実によってあなたは救われます。

最後に、割り当てを試してみると、最初の割り当てで1回限りのエラーが発生します($campaign)。出力は:ssss_uk_01、であり、期待しssss_uk_01ます。

関数を正しく使用するにsubstrは、次を使用する必要があります。

$campaign = substr $campaign, 9;
$validity = substr $validity, 9;
$choice   = substr $choice, 7;
于 2012-12-01T14:16:04.567 に答える
0

ルックアップテーブルにハッシュを使用するというTLPの提案に同意します。ただし、実際のアプリケーションでは、他のテーブルのデータが変更されたときにアプリケーションを変更する必要がないように、これらのルックアップテーブルにデータベースルックアップを設定する必要があります。

また、ログ内のデータの形式を少し信頼しなくなる傾向があります。分割を使用すると、ラベルの正確な長さとコロンのサイズを知る必要がなくなります。その方針に沿って、ルックアップハッシュのキーとして使用する前にデータを正規化することもお勧めします。この例では、すべて小文字にしました。

警告を使用している間は、警告機能を使用してエラー状態について吠えることもできます。実際のアプリケーションでは、警告を電子メールアラートシステムに利用して、無人のソフトウェアに問題が発生したことを常に知ることができます。

or + dieイディオムは、ファイル操作を行う際の優れた方法です。ただし、印刷の場合でも、$ OS_ERROR(別名$!)を含めると、これらのダイが発生したときに、より多くの情報が得られます。このようにして、許可が拒否されたか、存在しないか、ディスクがいっぱいかなどの違いがわかります。

これらは、保守可能で回復力のあるプログラムを作成する際の問題を説明する提案です。しかし、私は個人的に、コードの美学も保守性に貢献していると信じています。意味のある命名規則とコードフォーマットは、改善またはバグ修正を行うために今から1、2年後にこのプログラムを開くときに、大きな違いを生む可能性があります。私は、明白なことを述べるコメントや、コードのブロックを削除するためのコメントの使用など、不要な混乱がないコードを作成することを好みます。

良い仕事を続けてください。世界はより多くのソフトウェア自動化を必要としています。

#!/usr/bin/perl

use strict;
use warnings;
use DBI;

#
# _voting.pl
#
my $logfile = '/var/www/voting/votes.txt';

my $errors = 0;

my %campaign_id_for = (
    'ssss_uk_01b' => 1,
    'ssss_uk_01c' => 2,
    'ssss_uk_01d' => 3,
    'ssss_uk_01e' => 4,
    'ssss_uk_01f' => 5,
    'ssss_uk_01g' => 6,
);

my %candidate_id_for = (
    'brown'   => 1,
    'cameron' => 2,
    'balls'   => 3,
    'green'   => 4,
    'boring'  => 5,
    'tupele'  => 6,
);

my $dbh = DBI->connect( 
    'DBI:mysql:database=sms_voting;host=localhost',
    'sisisi', 
    '*********', 
    { 'RaiseError' => 1 } 
);

my $sth = $dbh->prepare(q{
    INSERT INTO voting (
        epoch,
        validity,
        choice,
        campaigns_id,
        candidates_id
    ) VALUES (
        ?,
        ?,
        ?,
        ?,
        ?
    )
});

my $fh;

open $fh, '<', $logfile
    or die "open $logfile: $!";

LINE:
for my $line (<$fh>) {

    my ($vote, $epoch,  $campaign, $validity, $choice,
        $CONN, $MSISDN, $GUID,     $Shortcode
    ) = split /\s+/, $line;

    ($campaign) = reverse split /:/, $campaign;
    ($validity) = reverse split /:/, $validity;
    ($choice)   = reverse split /:/, $choice;

    my $campaign_id  = $campaign_id_for{ lc $campaign };
    my $candidate_id = $candidate_id_for{ lc $choice };

    if ( $epoch && $validity && $choice && $campaign_id && $candidate_id ) {

        $sth->execute(
            $epoch,
            $validity,
            $choice,
            $campaign_id,
            $candidate_id
        );

        print "$epoch $validity $choice\n"
            or die "print: $!";

        next LINE;
    }
    else {

        warn "failed to parse: $line\n";
        $errors++;
    }
}

close $fh
    or die "close $logfile: $!";

# debug
print "error count: $errors\n"
    or die "print: $!";
于 2012-12-01T15:52:48.400 に答える