Perl: 2017年5月アーカイブ

久しぶりに DB データが「ハッシュの配列」にセットされまくってる感じの Perl プログラムのメンテを行うことになったので、ハッシュ(連想配列)のリファレンスなどについてメモ。

まあ、Perl の多次元配列については、木本裕紀さんの「Perl学習サイト - サンプルコードPerl入門」サイトの中の「配列とハッシュで多次元データ構造を自由に操る」がそのまま参考になる。

なので、ここで書いているのはその補足。

ハッシュ(連想配列)を配列にセットした、いわゆる「ハッシュの配列」を扱う場合。

下のコードは、PostgreSQL から取得したデータをセットしてる例(余分な処理は削ってるので、「例外に対する処理が甘い」とか、そういうツッコミはなしで(笑))

@persons = ();

# DB から $sql の条件でデータ取得(例えば、クラス名簿とか)
$result = $Conn->exec($sql);
if (!$result->resultStatus eq PGRES_TUPLES_OK) {
# DB エラーなら処理を抜ける
exit;
}

# 人数分データを読み込む
for ($i = 0 ; $i < $result->ntuples ; $i++) {
# DB から取得した名前、性別、年齢をハッシュにセット
my %person = ();
$person{'name'} = $result->getvalue($i, $result->fnumber(name));
$person{'sex'} = $result->getvalue($i, $result->fnumber(sex));
$person{'age'} = $result->getvalue($i, $result->fnumber(age));
# ハッシュを配列にセット
push @persons, \%person;
}

これで、クラス名簿が「ハッシュの配列」にセットされる。

全員のデータを読みだそうとしたら、

foreach $person (@persons) {
foreach $key (keys %$person) {
$value = $person->{$key};
print "$key : $value\n";
}
}

こうすれば抜き出せる。

結果は、

name : Masunori
sex : m
age : 23
name : Beiko
sex : f
age : 44
.....
name : Taro
sex : m
age : 18

こんな風に表示される。

では、全件出力するのではなく、最初の人のデータだけ読み出したいって場合。
例えば、一人目の人の性別を確認とか。

ポイントは、「ハッシュの配列」はただの配列ではなく、実際は「ハッシュのリファレンス」を要素に持つ「配列のリファレンス」ということ。
そのため、@persons を参照するには @$persons のように配列のデリファレンスを行なう必要あり。

print @$persons[0]->{'sex'};

このように書けばいいのね。これで「m」という結果が表示される。
以前、俺が Perl で書いた API プログラムについて「別サーバに移したら DBI モジュールが無くて動かないみたいなのでヨロシク」・・・という指示がお客さんからあったので対応。

CentOS サーバなのだが、

# perl
use DBI;
Can't locate DBI.pm in @INC (@INC contains: /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8 <略> .) at - line 1.
BEGIN failed--compilation aborted at - line 1.

確かに DBI モジュールがインストールされていないようなので入れる。

このサーバ、ローカルネットワークの外には出れないようになっているので、インターネットに接続できる Windows PC でダウンロードしたファイルをサーバに SFTP アップして作業をする。

取ってくるファイルは、最新のアーカイブ。
CPAN サイト
から、DBI-1.636.tar.gz をダウンロードし、サーバに上げて以下作業を行った。

# tar xvfz DBI-1.636.tar.gz
DBI-1.636/
DBI-1.636/Changes
DBI-1.636/dbd_xsh.h
DBI-1.636/DBI.pm
<略>
DBI-1.636/ex/corogofer.pl
DBI-1.636/ex/perl_dbi_nulls_test.pl
DBI-1.636/ex/profile.pl
# cd DBI-1.636
# perl Makefile.PL

*** Your LANG environment variable is set to 'ja_JP.UTF-8'
*** This may cause problems for some perl installations.
*** If you get test failures, please try again with LANG unset.
*** If that then works, please email dbi-dev@perl.org with details
*** including the output of 'perl -V'

Your perl was compiled with gcc (version 4.1.2 20080704 (Red Hat 4.1.2-55)), okay.
Creating test wrappers for DBD::Gofer:
t/zvg_01basics.t
<略>
Checking if your kit is complete...
Looks good
Warning: prerequisite ExtUtils::MakeMaker 6.48 not found. We have 6.30.
Warning: prerequisite Test::Simple 0.90 not found. We have 0.62.

    I see you're using perl 5.008008 on x86_64-linux-thread-multi, okay.
    Remember to actually *read* the README file!
    Use  'make' to build the software (dmake or nmake on Windows).
    Then 'make test' to execute self tests.
    Then 'make install' to install the DBI and then delete this working
    directory before unpacking and building any DBD::* drivers.

Writing Makefile for DBI

ExtUtils::MakeMaker
Test::Simple
この2つのバージョンが古いって警告(Warning)が出てるけど、この2つを入れ直そうとすると依存関係すごそう(^^;
上に書いたように、依存関係のあるモジュールについても一個一個手動インストールするしかないんで、「ま、Warning なんで・・・」と、とりあえず無視してインストールしちゃう。

# make
<略>
Manifying blib/man3/DBI::DBD.3pm
Manifying blib/man3/Win32::DBIODBC.3pm
Manifying blib/man3/DBI::DBD::SqlEngine.3pm
Manifying blib/man3/DBI::PurePerl.3pm
Manifying blib/man3/DBI::ProfileData.3pm

特にエラーは出てない。問題なく make できたっぽいなあ。
まあ、make test は予想どおりボロボロですけど。

# make test
<略>
Failed Test                    Stat Wstat Total Fail  Failed  List of Failed
-------------------------------------------------------------------------------
t/06attrs.t                     255 65280    ??   ??       %  ??
t/08keeperr.t                   255 65280    ??   ??       %  ??
t/10examp.t                     255 65280   238  476 200.00%  1-238
t/42prof_data.t                 255 65280    31   58 187.10%  3-31
t/48dbi_dbd_sqlengine.t         255 65280    ??   ??       %  ??
<略>
t/zvxnp_52dbm_complex.t         255 65280    ??   ??       %  ??
t/zvxnp_85gofer.t               255 65280    ??   ??       %  ??
32 tests and 225 subtests skipped.
Failed 74/194 test scripts, 61.86% okay. 1010/4579 subtests failed, 77.94% okay.
make: *** [test_dynamic] エラー 255

ずいぶんエラーが発生しているけど、

t/zvp_10examp.t                 255 65280   238  476 200.00%  1-238

のように、全テスト件数が 238 なのに、faild になったエラーが 476件あって、エラー発生率 200%というおかしなものも混ざっているので、とりあえず無視。

インストールしてみる。

# make install
Installing /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/DBI/DBIXS.h
Installing /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/DBI/Driver.xst
Installing /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/DBI/DBI.bs
<略>
Installing /usr/bin/dbiprof
Installing /usr/bin/dbilogstrip
Writing /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/DBI/.packlist
Appending installation info to /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/perllocal.pod

まあ、インストールはファイルのコピーするだけだからイクわな。

# perl
use DBI;

とりあえず、エラーは出なくなった。
次は DBD::Pg モジュールのインストール。

このアーカイブについて

このページには、2017年5月以降に書かれたブログ記事のうちPerlカテゴリに属しているものが含まれています。

前のアーカイブはPerl: 2016年5月です。

次のアーカイブはPerl: 2017年7月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら