1. ホーム
  2. スクリプト・コラム
  3. パール
  4. アプリケーションのヒント

Perlの特殊な組み込み変数の詳細

2022-01-29 19:29:21

組み込み変数 $_ です。

まずは例題から。

コピーコード コードは以下の通りです。

#! /usr/bin/perl -w
@array = qw(a b c d);
foreach (@array) {
 print $_," ";
}

この例で行っているのは、配列を定義して、その中の要素をプリントアウトすることです。ここで注意すべきは、foreachループの部分です。foreachループの標準的な書式は以下の通りです。
コピーコード コードは以下の通りです。
foreach $element (@array){
 ......
}

ここで、@arrayという配列は、$elementに順番に要素を代入するのですが、上記のプログラムでは、それをせずに、perlに組み込まれている特殊な変数$_を使いました。
プログラムの5行目の foreach (@array) は、実は foreach $_ (@array) と同じで、$_ はデフォルトの入出力なので、プログラム中に明示的に宣言されていない同様の変数位置があれば、代わりに $_ を使うことができるかもしれません

組み込み変数 $$.

コピーコード コードは以下の通りです。
perl -e "sleep(5); print qq (The PID of process perl.exe is : $$)"; 

これは、コマンドラインで使用するPerlプログラムで、特殊変数$$が存在する場合、print qq (The PID of process perl.exe is : $$)というパラグラフをプリントアウトする役割を果たします。
$$は現在のPerlパーサーのプロセスID(=PID)です。この段落のプログラムをコマンドラインに書くと、Perlパーサが実行されてから5秒後にPerlパーサのプロセスIDがプリントされ、プログラム実行中にプロセスのリストを確認することで、そのプリントが正しいかどうかを確認することができます。

組み込み変数 $! :

次に、エラーメッセージ(またはエラー番号)を返すために使用する特殊な変数です。
時間を節約するために、プログラムを書く代わりに、コマンドラインのものを用意しましょう。

コピーコード コードは以下の通りです。
perl -e "opendir FH,'c: one' or die qq (can't open:$!) ;";

この文は、Cドライブの下に何もないディレクトリを開くことです(そして、私は実際に私のCドライブにこのディレクトリを持っていない、私がこれを書いた理由は、プログラムのエラーメッセージを引き起こすことです)、開いていない場合、それは後者を実行しますダイqq(開くことができない:$!)。
ここでは、次に$!でエラーメッセージの内容を指定し、コマンドラインではそのエラーメッセージを返しています。
コピーコード コードは以下の通りです。
can't open:No such file or directory at -e line 1.

はopenやopendirでよく使われます(ファイルやパイプなどを開くかどうか)。

例として、面白い特殊な組み込み変数を紹介します。

コピーコード コードは以下の通りです。
$text = "C:\test.txt";
{
 open FH,$text or die "can't open:$! ";
 my $line = ;
 close FH;
 print $line;
}
print "#===========================# ";
{
 undef $/;
 open FH,$text or die "can't open:$! ";
 my $line = ;
 close FH;
 print $line;
}

=================================
Cドライブ下のtest.txtの中身は。
1111111111111111111111111
222222222222222222222222222
33333333333333333333333333333333333
=================================
OK、次のような結果でプログラムが実行されます。
1111111111111111111111111
#===========================#
1111111111111111111111111
222222222222222222222222222
33333333333333333333333333333333333

プログラムはもう無意味、役割はファイルを読むこと、"$line ="の中の重要な部分、尖ったブラケット演算子(つまり<>)の役割はファイルの内容を1行読むこと(ほとんどのチュートリアルや本はこのように書かれていると思います)、しかし、ここで1行と言っているのは、実は基準がある、つまり改行に遭遇したときにperlが1行とみなす、特殊変数$/による初期値である、この基準から、1行を1列と見なす。
つまり、Perl が <> 演算子でファイルを読み込むたびに、まず $/ から "separator" というものを取得して、その区切り文字を目印にしてファイルを読み込むのですが、$/ がデフォルトで使われている場合は改行文字になっているので、デフォルトでは <> ; 演算子は一度に一行のテキストのみを読み込むことになるのです。
与えられた例では、次の行があります:undef $/ これは $/ を未定義の値に設定し、$/ が機能しなくなるようにします。したがって、2回目に同じことをすると、 <> 演算子は単に1行を読むのではなく、ファイル全体を読むことになることがおわかりでしょう。

次に、$/の影響を受ける組み込み変数を見てみましょう。ここでも、まず例題から。

コピーコード コードは以下の通りです。
$text = "C:\test.txt";
open FH,$text or die "can't open:$! ";
while () {
 print "line $. is:$_";
}
close FH;

まず、ループを見てみましょう: print "line $. is:$_"
このプログラムの機能は、ファイルを読み込んで、一行ずつ、$_に代入することです(<>演算子だけが使われ、内部の代入変数が指定されていないので、デフォルトは$_に代入されます)。
しかし、ここでは $_ の他に "$." という変数が存在します。
その結果を見てみましょう。
コピーコード コードは以下の通りです。
line 1 is:111111111111111111111111111111
line 2 is:222222222222222222222222222222222222
line 3 is:333333333333333333333333333333333333

このように、変数$.はカウンターのようなものですが、なぜ冒頭で$.は変数$/の影響を受けると言ったのでしょうか。

上の例を少し修正して、もう一度見てください。

コピーコード コードは以下の通りです。
$text = "C:\test.txt";
undef $/; # Note that the extra line
open FH,$text or die "can't open:$! ";
while () {
 print "line $. is:$_";
}
close FH;

2行目は、このプログラムが何をするのか見るために、上記で説明したundef $/; を追加しています。

コピーコード コードは以下の通りです。
line 1 is:111111111111111111111111111111
222222222222222222222222222
33333333333333333333333333333333333

3行になるはずのテキストが一度に出力されるだけでなく、"line 1"と指定されている(プログラムがこのテキストを1行だけだと考えているようだ)。
これは、プログラムを見ればわかると思うが、変数 $. は単なる行数カウンタではなく、$/ に対するカウンタだからである。
コピーコード コードは以下の通りです。
$text = "C:\a.txt";
$/ = ";"; # Notice here that I didn't set $/ to undefined, but gave it a semicolon
open FH,$text or die "can't open:$! ";
while () {
 print "line $. is:$_ ";
}
close FH;

Cドライブの下にあるa.txtの内容をもう一度見てみましょう。

コピーコード コードは以下の通りです。
ddd;bbb;ccc;fff;eee;

とてもシンプルなことです。
走った結果を見てください。
コピーコード コードは以下の通りです。
line 1 is:ddd;
line 2 is:bbb;
line 3 is:ccc;
line 4 is:fff;
line 5 is:eee;

このプログラムを読めば、理解できるはずです。

さて、$。 これでだいたいのことはわかったので、もうひとつ、やはりプログラムを見ながら、その特徴について話そう。

コピーコード コードは以下の通りです。
$text = "C:\test.txt";
open FH,$text or die "can't open:$! ";
while () {
 print "line $. is:$_ ";
}
print " ",$. ;
close FH;
print " ",$. ;

このプログラムで注目すべきは、2つのプリント " ",$. ; (1つはファイルを閉じる前、もう1つは閉じた後)です。
実行結果を見てみましょう。
コピーコード コードは以下の通りです。
line 1 is:111111111111111111111111111111
line 2 is:222222222222222222222222222222222222
line 3 is:333333333333333333333333333333333333
3
0

結果の最初の3行は既知のもので、私たちが気にかけるべきは、結果の最後の2行(つまり、2つのprint "、$.;の結果)です。
変数$.はニモニック(原理的にはパケット変数)なので、ファイルを閉じる前に印刷すると、その値がまだ変化していないことがわかります(その時点の値と前回ファイルを読んだときの値はともに3です)。
そして、ファイルを閉じた後、この変数は再び0に初期化されます。
この機能は注意すれば問題ないのですが、その原理にはPerlのスコープやパッケージの知識が必要で、あまり簡単に説明できないので、パッケージやスコープを知っている読者なら、この部分は話さなくても理解できるはずなので、ここでは割愛します。

組み込み変数: $^O.
もう一度、最後の1枚について説明します
オペレーティングシステムの種類を判断する簡単な方法として、例を見てみましょう。

コピーコード コードは以下の通りです。
C:>perl -e "print $^O;";
MSWin32

ここでは、この特殊変数$^Oの最後の文字がOであり、大文字であることに注意してください。
もし、リナックス環境であれば、結果はMSWin32ではなく、リナックスになります ;)
これは環境を決定するための変数で、シンプルで便利です。