|
|
Perlプログラム作成の変数 |
H.Kamifuji . |
変数は文字や数値などをプログラムの中で扱う場合にその値を保存する時に使用します。ここでは値を保存するために利用する変数という概念について確認していきます。 当ページでは、Linux CentOS7 の Gnome で動作テストしています。 |
|
まず変数とは何かについて確認しておきます。 同じ文字列を5回表示するようなプログラムを考えて下さい。 print "こんにちは\n"; print "こんにちは\n"; print "こんにちは\n"; print "こんにちは\n"; print "こんにちは\n";このプログラム自体には何の間違いもありませんし思った通りの動作をします。ここで繰り返し表示したい文字列が「こんにちは」ではなくて「こんばんは」だったことが分かったとします。その場合にはプログラムを次のように書き直さなくてはなりません。 print "こんばんは\n"; print "こんばんは\n"; print "こんばんは\n"; print "こんばんは\n"; print "こんばんは\n";今回の場合は修正箇所も5回だけですし、同じ位置にまとめて記述されていますので修正するのも簡単です。ただプログラム中の別々の場所に記述されていたような場合には探し出して修正するのは結構大変です。また修正忘れによるミスにもつながりやすくなります。 「こんにちは」にしても「こんばんは」にしても、何か記憶できる場所を用意しておいて値を保管しておき、必要に応じて取り出すことができれば便利です。値を保管する場所を変数といいます。 変数と呼ばれる保管場所に「こんにちは」と言う文字列を格納しておくでは変数を使って先ほどのプログラムを書き直してみます。 my $str = "こんにちは\n"; print $str; print $str; print $str; print $str; print $str;変数の詳しい使い方は次のページ以降で解説しますが、今回のプログラムでは1行目で変数「str」に文字列「こんばんは\n」を格納しています。そして変数「str」に格納されている値を5回出力しています。 「こんばんは」と言う文字列は変数に1回だけ格納していますので、もし出力したい文字列が変更になった場合でも1箇所だけを変更するだけで済みます。 my $str = "こんばんは\n"; print $str; print $str; print $str; print $str; print $str;「print」で文字を出力する部分には出力する文字列を記述していませんので何も修正する必要はありません。修正する箇所は変数に文字列を格納する部分だけです。 このように変数をうまく活用することでプログラムを効率よく記述することが出来ます。変数には値を保存するだけではなく、一度保存した値を書き換えることも可能なので、例えば一度変数に保存した値を取り出して別の加工をした上で再度変数に保存し直すと言った事も可能です。 また変数に数値を格納した場合、変数に対して演算を行うこともできます。計算の結果を変数に格納しておき、その格納された値にまた別の計算を行って再度変数に格納するといったことも可能です。 では簡単なプログラムで確認して見ます。 サンプルプログラム下記のサンプルを実行してみよう。# 変数とは use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $str = "こんにちは\n"; print $str; print $str; print $str; $str = "こんばんは\n"; print $str; print $str; print $str;上記を「test1-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 変数に格納された値が出力されています。今回の例では途中で変数に別の値を再度格納してからまた出力しています。 それでは次のページ以降で変数について詳しく確認していきます。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test1-1_u.pl | nkf -w こんにちは こんにちは こんにちは こんばんは こんばんは こんばんは [xxxxxxxx@dddddddddd Var]$ |
変数というのはプログラムの中で1つしか使えないわけではありません。複数の変数をプログラム中で用意し使い分けることが出来ますので、複数の値を格納しておくことが可能です。 複数の変数を使用する場合にはそれぞれの変数を区別しなくてはなりません。その為に変数にはそれぞれ名前を付ける事になっています。変数に付ける名前を「変数名」と呼びます。 「str」と言う変数名を持つ変数に「b」と言う文字列を格納する 「old」と言う変数名を持つ変数に「10」と言う数値を格納する上記では「str」や「old」が変数名となります。 変数名の規則変数名は任意の名前をつけることが出来ますが次のような規則があります。変数名にはアルファベット・数字・アンダーバー("_")を使うことが出来ます (例) name, old20, _hokan 先頭の文字に数字は利用できません (例) 10kago は不可 大文字と小文字は区別します。 (例) old と Old は別の変数名となります変数名は規則にしたがっている限り好きな名前を使えますが、例えば「bb1」「bb2」「bb3」のような意味が分かりにくい変数名を付けると、変数にどんな値が含まれているか分かりません。出来るだけどんな値を格納するのかが分かるような名前をつけることをお勧めします。 |
文字列や数値などの値を格納するためのものを単に変数と呼ぶことが多いですがPerlでは変数にはいくつか種類があります。単に値を格納するために使われる変数は正式にはスカラー変数と呼ばれるものです。 Perlではスカラー変数の他に配列変数、ハッシュ変数(連想配列変数)などがあります。
単に変数と呼ぶときはスカラー変数のことを指していると考えて下さい。 変数の宣言Perlで変数を使用する場合には変数を宣言する必要があります。変数の宣言には変数の種類毎に用意されたプレフィックスに変数名を付けて記述します。プレフィックス + 変数名変数の種類毎のプレフィックスと使用例は次の通りです。
スカラー変数を使用する場合は例えばプログラムの中で次のように記述します。 $var;これで変数名「var」と言うスカラー変数を宣言したことになります。変数を宣言すると今後変数を利用することが可能となります。 変数の有効範囲Perlにおいて前述したような変数の宣言を行うとプログラム中のどこでも使用できる変数となります。どこでも使用できる変数は便利な反面、予期しない問題を起こす事もあります。そこで変数が有効となる範囲を出来るだけ限定し、有効範囲を抜けると変数が使えなくなるようにしておくことでトラブルを未然に回避することが出来ます。変数が宣言されたブロック内でのみ有効とするには変数宣言の前に「my」を記述します。(ブロックなどの考え方については別のページで詳しく見ていきますので取りあえず気にしないで下さい)。 my $var;「my」はスカラー変数だけではなく配列変数やハッシュ変数にも使用することが出来ます。 my @var; my %var;複数の変数に対して「my」を使用する場合は次のように記述することも出来ます。 my ($a, $b, %c);今後変数を使用する場合には基本的に「my」を付けて変数を宣言します。 |
変数を宣言することでプログラム中で変数が利用できるようになります。そこでここでは変数に値を格納する方法を確認していきます。 変数は値を格納する場所ですので変数を宣言すると場所だけが作成されています。値を格納するまでは変数という場所には何が入っているか分からない状態となっています。 実際に変数を宣言だけ行って値を格納しない状態で変数の値を出力させてみます。 サンプルプログラム下記のサンプルを実行してみよう。# 値を格納 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $var; print $var;上記を「test4-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 初期化されていない変数から値を取り出そうとしたために警告が表示されました。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test4-1_u.pl | nkf -w Use of uninitialized value $var in print at test4-1_u.pl line 10. [xxxxxxxx@dddddddddd Var]$ 変数に値を格納するでは宣言された変数に対して値を格納してみます。変数に値を格納するには次の書式を使います。変数名 = 値;通常「=」と言うのは左辺と右辺が等しいと言う意味で使われますが、プログラミングで使用する場合には右辺を左辺へ代入するという意味で使われます。よって上記の場合には値を変数に格納するという意味になります。具体的には次のようになります。 my $str; $str = "Hello";上記の場合には変数名「str」と言う変数を宣言し、そして「str」と言う変数に文字列の「Hello」を格納しています。 では変数に格納された値を画面に出力してみます。文字列や数値と同じく「print」関数を使って出力します。 サンプルプログラム下記のサンプルを実行してみよう。# 値を格納 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $str; $str = "Hello"; print $str;上記を「test4-2.pl」の名前で保存してから次のように実行して下さい。 ![]() 変数に格納された値が画面に出力されました。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test4-2_u.pl | nkf -w Hello [xxxxxxxx@dddddddddd Var]$ |
変数は一度値を格納した後で別の値を格納することが出来ます。ただし1つの変数につき値を格納できる場所は1つしかありませんので、新しい値を格納すると古い値は上書きされて消えてしまいます。 次のサンプルでは変数を1つ宣言し、初期値を一度格納してから画面に出力し、その後で別の値を変数に格納してから改めて画面に出力しています。 test5-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 別の値を格納 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $str; $str = "Hello"; print $str; $str = "こんにちは"; print $str; print "\n";上記を「test5-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 画面に出力している箇所は「print $str;」と同じなのですが、この部分が実行されている時に変数「$str」に格納されている値を出力しているため同じプログラムであっても別の値が画面に出力されています。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test5-1_u.pl | nkf -w Helloこんにちは [xxxxxxxx@dddddddddd Var]$ 同じ変数に異なる種類の値を格納Perlで扱う値としては数値や文字列などがあります。他のプログラムの言語では変数に格納できる値の種類を指定して変数を宣言するものもありますが、Perlでは変数に格納できる値を限定していません。その為、宣言した変数に一度文字列を格納した後で、同じ変数に対して今度は数値を格納することが可能です。次のサンプルでは変数を1つ宣言し、初期値を一度文字列を格納してから画面に出力し、その後で今度は数値を変数に格納してから改めて画面に出力しています。 サンプルプログラム下記のサンプルを実行してみよう。# 同じ変数に異なる種類の値を格納 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $str; $str = "Hello"; print $str; $str = 10; print $str; print "\n";上記を「test5-2.pl」の名前で保存してから次のように実行して下さい。 ![]() このように同じ変数に対して異なる種類の値を格納することが可能です。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test5-2_u.pl | nkf -w Hello10 [xxxxxxxx@dddddddddd Var]$ |
今までは変数を宣言した後で変数に値を格納していましたが、変数の宣言を行うと同時に初期値を格納することが出来ます。次の書式を使います。 my $変数名 = 初期値;上記は次のように記述した場合と同じです。 my $変数名; $変数名 = 初期値;宣言と同時に値を格納することで、値が格納されていない変数を使用するミスを未然に防ぐことができます。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。# 変数の宣言と初期化 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $str = "Hello"; print $str; print "\n";上記を「test6-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 結果は変数の宣言と値の格納を別々に行った場合と同じです。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test6-1_u.pl | nkf -w Hello [xxxxxxxx@dddddddddd Var]$ |
変数には数値や文字列の値を格納することができますが、値を直接格納する以外に他の変数に格納されている値を格納することが出来ます。 my ($var1, $var2); $var1 = 100; $var2 = $var1;上記の場合は、まず2つの変数を宣言します。そして変数「$var1」に数値の100を格納します。次に変数「$var2」に変数「$var1」を格納します。この時、変数「$var2」には変数「$var1」に格納されている値が取り出されて格納されます。結果として変数「$var2」には数値の100が格納されます。 この時、変数「$var1」の値がコピーされて変数「$var2」に格納されますので変数「$var1」には数値の100が格納されたままです。また値がコピーされているだけなので、後で変数「$var1」の値が変更されたとしても変数「$var2」の値には影響しません。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。# 他の変数の値を格納 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my ($var1, $var2); $var1 = "Hello\n"; $var2 = $var1; print $var1; print $var2; $var1 = "こんにちは\n"; print $var1; print $var2;上記を「test7-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 今回の場合、まず変数に文字列を格納した後で他の変数にコピーして画面に両方の変数の値を出力させています。そして変数の値を1つだけ変更してから改めて両方の変数の値を出力させています。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test7-1_u.pl | nkf -w Hello Hello こんにちは Hello [xxxxxxxx@dddddddddd Var]$ |
文字列を定義するにはダブルクオーテーション(")で囲う方法とシングルクオーテーション(')で囲う方法の2つの方法があることは既に解説しました。 "こんにちは" 'お元気ですか'この中でダブルクオーテーションで囲っている場合には、文字列の中に変数を記述することで、変数が記述された位置に変数に格納された値を置き換えさせることが出来ます。 my $name = "加藤"; print "こんにちは $name さん";上記では画面に「こんにちは 加藤 さん」と言う文字列が出力されます。ダブルクオーテーションで囲まれた文字列の中に記述された変数が、変数に格納されている値に置き換えられるためです。 これは次のように文字列の連結を使って記述した場合と同じです。 $name = "加藤"; print "こんにちは ".$name." さん";今度の場合は「こんにちは」と変数「$name」と「さん」の3つが連結されて変数「$msg」に格納されることになります。記述方法としては間違いではありませんが文字列中に直接変数を記述した方が簡潔に記述することが出来ます。 文字列中の変数展開が行われるのはダブルクオーテーションで囲まれた文字列だけです。シングルクオーテーションで囲まれた文字列の中に変数を記述しても、それは単なる文字として扱われるので変数とは認識されません。 my $name = "加藤"; print 'こんにちは $name さん';上記では画面に「こんにちは $name さん」と言う文字列が出力されます。 では実際に試してみます。 test8-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 文字列中の変数展開 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $name = "加藤"; print "こんにちは $name さん\n"; print "こんにちは ".$name." さん\n"; print 'こんにちは $name さん'."\n"; print 'こんにちは '.$name.' さん'."\n";上記を「test8-1.pl」の名前で保存してから次のように実行して下さい。 ![]() ダブルクオーテーションで囲まれた文字列の場合は変数の値が展開されているのに対して、シングルクオーテーションで囲まれた文字列の場合は変数の展開がされていないことが確認できます。なおどちらの場合も文字列の連結を行った場合は同じ結果です。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@ddddddddd Var]$ perl test8-1_u.pl | nkf -w こんにちは 加藤 さん こんにちは 加藤 さん こんにちは $name さん こんにちは 加藤 さん [xxxxxxxx@ddddddddd Var]$ |
文字列中に変数展開を行う場合には注意する点があります。次の例で考えみます。 my $name = "加藤"; print "Hello,$namesan";上記の場合、文字列中に変数が含まれていますが、変数名として「$name」ではなく「$namesan」と言う変数に格納されている値を展開しようとします。変数の展開は宣言されている変数を検索して行うといったものではなく、文字列中に含まれていて「$」から開始し、変数名として使用できるアルファベットや数字やアンダーバーが途切れるまでを変数名としてみなします。 その為、変数名の直後にアルファベットや数字やアンダーバーが記述されている場合は、意図していない変数として扱われてしまいます。これを防ぐには変数名の直後は変数名として使用できない空白などの文字を記述して変数がどこからどこまでなのかを明確にします。 my $name = "加藤"; print "Hello,$name san";ただしこの方法では変数名の直後にアルファベットや数字を記述できません。そこで直後にアルファベットや数字を記述したい場合は変数名を括弧{}で囲んで記述します。 my $name = "加藤"; print "Hello,${name}san";このように記述することで文字列中の含まれる変数が「$name」であることを明確に表すことが出来ます。 では実際に試してみます。 test9-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 変数展開時の変数名と文字列の区切り use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $name = "加藤"; print "Hello,$name san\n"; print "Hello,${name}san\n";上記を「test9-1.pl」の名前で保存してから次のように実行して下さい。 ![]() どちらの場合も文字列中の変数展開が正常に行われています。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test9-1_u.pl | nkf -w Hello,加藤 san Hello,加藤san [xxxxxxxx@dddddddddd Var]$ |
|