Perl Perl_0
Perl 「 ハッシュ 」: ( Hash ) %ENV を確認する (0x53)

目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x53 回。
Perl 組み込みハッシュ「 %ENV 」を利用して、システムの環境変数を確認する。
%ENV と環境変数
Perl には、「 %ENV 」という予め組み込まれたハッシュが存在します。
「 ENV 」は、英語の「 Environment 」の略です。Environment は「 環境 」を意味する言葉で、Perl の「 %ENV 」はシステムの環境変数を格納しています。
コンピュータのオペレーティングシステムやシェル等には、予め全体で設定を共有するための「 環境変数 」という機能が備わっています。
例えば、Unix 系のシステムであれば、標準のエディタを表す「 EDITOR 」や、じぶんのホームディレクトリを表す「 HOME 」等々が存在します。いわゆる「 パスを通す 」と言うのは、環境変数「 PATH 」を設定することです。
Perl の組み込みハッシュ「 %ENV 」は、そのプログラムが実行されている時点で、現在設定されている環境変数の値を持っています。
「 %ENV 」はハッシュなので、keys/values 関数を使ってその値を確認出来るわけです。
Perl のプログラムで環境変数を表示する
次のプログラムは、printf 関数と、「 最高水位線 」( High-water mark ) のアルゴリズムを利用した環境変数一覧を表示するプログラムです。
my $col_length = &sub_length (keys %ENV);
printf "%-${col_length}s = %-${col_length}s\n", ("[ ENV ]", "[ Value ]");
foreach my $key ( sort keys %ENV ) {
printf "%-${col_length}s = %-${col_length}s\n", ($key, $ENV{$key});
}
sub sub_length {
my ($ref_length) = shift @_;
my $max_length = length $ref_length;
foreach (@_) {
my $next_length = length $_;
if ( $next_length > $max_length ) {
$max_length = $next_length;
}
}
$max_length;
}
まず、1 行目では、サブルーチン「 &sub_length 」の呼び出しをして、引数として「 %ENV 」の key を渡しています。
keys 関数で取り出される「 %ENV 」の key は、環境変数の名前です。
サブルーチン &sub_length の処理 (最長文字列長を抽出する)
次に、9 行目から書かれているサブルーチン「 &sub_length 」を見てみます。
ここでは、最も長い環境変数名の文字列長を抽出します。抽出された最長の文字列長は、メインルーチンの 3 行目以降で printf 関数のフォーマットに利用するためのものです。
サブルーチン %sub_length の中の 1 行目にあたる 10 行目では、サブルーチンの引数が格納されている、暗黙の配列変数「 @_ 」から、shift 演算子で値を 1 つ取り出して、スカラ変数「 $ref_length 」に代入しています。
ここで取り出される値は、ハッシュ %ENV の key、つまり環境変数の名前です。
$ref_length の値は、文字列長の「 最初の基準 」にするだけなので、shift 演算子の代わりに pop 演算子を使っても支障はありません。
* 「 Perl でスタックな配列のデータ操作する : pop 演算子 (0x21) 」
* 「 Perl pop & push に対する shift & unshift 演算子 (0x23) 」
11 行目では、「 length 」という関数を使って $ref_length の文字列長の値を「 $max_lenght 」に代入しています。length 関数の機能によって、$max_length には、純粋に文字列の長さだけが代入されます。
13 行目の foreach 文では、@_ に残った値をひとつずつ取り出して、その長さを「 $next_length 」に代入しています。
これを、15 行目の if 文の条件式の中で、 $max_length の長さと比較する様にしています。
条件の内容は、$next_length の方が大きければ 真 となり、その値を $max_length に上書きする。逆に小さければ 偽 となるため、値の上書き処理を素通りして、次のループに移るというものです。
これを繰り返すことで、最終的に $max_length の値が、最も長い文字列長になる算段です。
19 行目では、サブルーチンの中で最後に評価される式として、$max_length を置いています。サブルーチンは、最後に評価した式の値を戻り値として返すからです。
* 「 Perl 「 サブルーチン (Subroutine) 」: 戻り値 (0x30) 」
メインルーチンで printf を使った出力をする
サブルーチンの最後の値 $max_length が評価された後は、メインルーチンの1 行目に戻ります。
サブルーチン &sub_lnegth は、最後に評価した $max_length の値を返すので、スカラ変数「 $col_length 」には、%ENV の環境変数名の中で最長の文字列長の値が代入されます。
続く 3 行目の printf 関数では、ハッシュのシジルと同じ「 % 」記号が出てきますが、これは printf 関数の変換指定子に使うプレフィクスなので、混同しない様に注意します。
*「 Perl 「 printf 」: 整形各種 (0x3d) 」
printf のフォーマット
該当する printf 文を抜き出して、どのようなフォーマットを構成しているか確認してみましょう。
# 第 1 引数 (FORMAT) # 第 2 引数 (LIST)
printf "%-${col_length}s = %-${col_length}s\n", ("[ ENV ]", "[ Value ]");
第 1 引数 FORMAT では、変換指定子「 %s 」、フラグ「 -n 」、スカラ変数「 $col_length 」を利用しています。「 %s 」は LIST の文字列に変換され、「 -n 」は「 n 」の数だけ左詰めで整形します。
$col_length には、環境変数名の最長文字列長「 N 」が格納されているため、「 %-Ns 」と指定していることと同じです。
「 N 」の部分 ( 文字詰めのための数値 ) が、プログラムを書く段階では分からないので、変数に置き換えている訳ですね。
$col_lengh を「 ${col_length} 」としているのは、printf に対して、それがスカラ変数名であることを明示するためです。仮に「 { } 」を省いてしまうと、末尾に「 s 」が付いた別の名前 ( $col_lengths )になってしまいます。
第 2 引数の LIST には、ただの ( リテラルの ) 文字列として「 [ ENV ] 」と「 [ Value ] 」を指定しています。
これは、出力される項目の見出しに使います。LIST で 2 つの文字列を指定しているので、FORMAT 側の変換指定子も 2 つ指定しています。
FROMAT 側にある「 = 」は、なんらかの意味をもった演算子の様に見えることもありますが ( 僕にはそう見えることが多い )、これは単なる文字としての「 = 」です。
foreach による %ENV の処理
5 行目の foreach 文は、このプログラムの最後の処理に当たります。
foreach の条件式には「 sort keys %ENV 」を指定しています。sort 演算子をこの様に指定すると、keys 関数で取り出した %ENV の key をソートしてくれます。
特に必要性の無い並び替えですが、ソートされていると爽やかです。
foreach の制御変数を「 my %key 」としているのは、それがハッシュの key であることを分かりやすくするためです。暗黙のスカラ変数「 $_ 」を使っても問題ありません。
foreach ブロック内にある printf 文の FORMAT は、3 行目のものと同じですが、LIST の方はハッシュの key を格納している制御変数 $key と、ハッシュの value を呼び出すための $ENV{ $key } を指定しています。
これで、左カラムに環境変数の名前が、右カラムにその値が並ぶことになります。
foreach による %ENV の処理
このプログラム内で使い回しされている printf のフォーマットは、次の様にスカラ変数に代入することで、すっきりさせることが出来ます。
my $format = "%-${col_length}s = %-${col_length}s\n";
printf "$format", (LIST);
プログラムの実行結果
このプログラムの実行結果は次の様になります。
[ ENV ] = [ Value ]
BLOCKSIZE = K
EDITOR = vi
GROUP = group name
HOME = /home/your/home_directory
HOST = your host name
HOSTTYPE = FreeBSD
LANG = ja_JP.eucJP
LOGNAME = your login name
MACHTYPE = x86_64
MAIL = /var/mail/your_mailbox
OSTYPE = FreeBSD
PAGER = less
PATH = /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
PWD = /home/your/home_directory/current_dirrectory
REMOTEHOST = your.remote.host.name
SHELL = /bin/tcsh
SHLVL = 1
SSH_CLIENT = ***.***.**.*** 61292 22
SSH_CONNECTION = ***.***.**.*** 61292 ***.***.***.*.**
SSH_TTY = /dev/pts/2
TERM = xterm
USER = user name
VENDOR = amd
カッコイイですね。
0x53 -> 0x54 へ
次回は each 関数について確認します。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)