Study of CGI

演算子

スカラー演算子

演算子(operator)は、1個以上の値(オペランド:operand)をもとに、新しい値(結果:result)を生み出すものです。たとえば、プログラムでは無い一般になじみの深い足し算を例に挙げると、1+2は3となります。これは、当たり前ですがプログラムでもまったく同じで、この場合「1」と「2」という値(オペランド:operand)から、「3」という新しい値(結果:result)が、+という演算子(operator)によって生み出されたということになります。

数値の演算子(算術演算子)

演算子でもっともよく使われるのは、いわゆる四則計算を行うための演算子で、「+」足し算、「-」引き算、「*」掛け算、「/」割り算、「%」割った余り、「**」乗算、といったものでしょう。

使い方は、学校で習う数学の数式と同様です。

[使用例]

2 + 3 2足す3で5
5.1 - 2.4 5.1引く2.4.。約2.7
3 * 12 3かける12で36
14/2 14割る2で7
10.2 / 0.3 10.2割る0.3で約34
10/3 割り算には常に浮動小数点演算で行われるので約3.33333333333...
2 ** 3 2の3乗で8
10 % 3 10を3で割ったときの余り1

この使用例で一部「約」という言葉が使われています。

これは、コンピューター上の処理の問題で、たとえば14÷2が厳密には7にはならないという意味で「約」がついているのですが、実用上この約はほとんど考える必要はありません。

文字列の演算子

文字列値は、「.」ピリオド演算子によって連結されます。

文字列を連結するためには必ずピリオド演算子が必要で、文字列同士を隣り合わせにおいても連結されることはありません。

[使用例]

"hello" . "world" "helloworld"と同じ
"hello world" . "\n" "hello world\n"と同じ
"red" . " " . "green" "red green"と同じ

文字列特有の演算子には関数には、文字列繰り返し演算子(string repetition operator)があります。文字列繰り返し演算子は、英子文字x(エックス)を用い左オペランドの文字列を右オペランド(数値)で指定した回数だけ繰り返すことができます。

[使用例]

"red" x 3 "redredred"となる
"green_" x (4 + 1) "green" x 5 なので "green_green_green_green_green_" となる
(3 + 2) x 4 これは "5" x4 のことで"5555"

この演算子を用いると、たとえ左オペランドが数字であっても、文字列に変換されて扱われます。

上の例で言うと、最後の例は数学的に(3+2)×4=20と思ってしまうかもしれませんが、「(3+2)」と「4」の間にあるのは「×」(かける)ではなく、「x」(小文字のエックス)ですので、数学的には成り立たず、5の4回繰り返しで、"5555"となります。

また、数学の「×」ですと「(3+2)」と「4」を入れ替えても、結果は同じですがこの文字列繰り返し演算子では、入れ替えた場合4 x (3 + 2)で、4を5回繰り返し結果は"44444"となり、二つのオペランドは可換ではありません。

数値と文字列の変換

数値演算子に文字列値を与えるとPerlは文字列値を自動的に数値へと変換すします。

たとえば、数値演算子「+」に" 123.45red"を加えると警告メッセージも出さずに数値123.45へと変換されます。まったく数字になっていない、文字列を与えると(たとえば"red")、やはり警告も出さずに変換が行われます。このような場合は常に「0」に変換されます。

同様に、文字列を必要とする演算子の場合、数字が与えられても自動的に文字列として扱われます。

この変換は、たいていの場合は必要であればPerlが自動的に行うので、数値か文字列かを意識する必要はほとんどありません。


比較演算子

比較演算子は、二つのオペランドを比較して、真(true)、偽(false)のいずれかの値を返すものです。比較条件に合致していれば真、しなければ偽、です。

この、比較演算子には、数値比較演算子(numeric comparison operator)と文字比較演算子(storing comparison operator)があります。

わざわざ、この2種類の比較演算子が用意してあるのは、数値で比較した場合と、文字列で比較した場合では結果が違うことがままあるからです。たとえば、100と9を数値で比較すれば、100が大きいということになりますが、文字で比べれば9が大きいということになります。

[使用例]

比較条件 数値 文字列
等しい == eq
等しくない != ne
より小さい > lt
より大きい < gt
より小さいか等しい <= le
より大きいか等しい >= ge

演算子の優先順位

演算子の優先順位(precedence)は、2つ以上の演算子が個々のオペランドに対してどのように作用するかを、定義したものです。

たとえば、 2 + 3 * 4という式では、一般的な数学の法則にのっとり、乗算の「*」を先に処理し、 2 + 12とし、次に加算の「+」を処理し、最終的に14 となります。

つまり、この場合乗算は加算より優先順位が高いということになります。

括弧を使う事もでき ( 2 + 3 ) * 4とすると、5 * 4となり、結果は20となります。

優先順位の同じ演算子の場合は、実行順序は結合(associativity)により決定されます。

つまり、3つ同じ優先順位の演算子が並んだ場合、結合で示された位置の演算子を先に処理し、その結果(結合したもの)と、残ったオペランドを演算子で処理します。

たとえば1+2+3の場合、「結合」は左なので、1+2を処理し3として、3+3=9です。

この場合、どこから処理しても結果は変わりませんが、場合によってはこの処理の順番によっては結果が変わってきてしまうので注意が必要です。

【演算子の結合と優先順位(高いものから低いものの順)】

(まだ出てきていない演算子もありますが、ここではそういうものだと思ってください)

結合 演算子
「リスト」演算子(左方向)
-> ( method 呼び出し、デリファレンス)
しない ++ -- (オートインクリメント、オートデクリメント)
** (べき乗)
! ~ \ + -
(論理not、ビットごとのnot、リファレンス演算子、単項のプラス、単項のマイナス)
=~ !~ (マッチする、マッチしない)
* / % x (乗算、除算、剰余、文字列繰り返し)
+ - . (加算、減算、文字列連結)
<< >>(ビットシフト演算子)
しない 名前付き単項演算子( chompなど)
しない < <= > >= lt le gt ge (「非等値性」比較演算子)
しない == != <=> nq ne cmp (「等値性」比較演算子)
& (ビットごとのand )
| ^ (ビットごとの or、ビットごとの xor )
&& (論理 and )
|| (論理 or )
しない .. ... (範囲演算子)
? : (3項の if/then/else 演算子)
= += -= *= など(代入及び代入演算子)
, => (カンマ、カンマの働きをする矢印)
しない リスト演算子(右方向)
not (論理 not )
and (論理 and )
or xor (論理 or、論理 xor )

 

スカラー演算子によるスカラー変数の操作

代入(assignment)

変数に対して値を設定することをいいます。演算子によって生み出された、新たな数値(結果)を変数に、収めることにより取り扱いが楽になります。スカラー変数に対して、もっとも多く行われる操作でしょう。

Perl の代入演算子はイコール記号で表され、代入演算子の左側の変数名に対して、右側の値が設定されます。

[使用例]

$a = 17 ; $aに値17を代入する。
$b = $a + 3 ; $bに、現在の$aの値に3を加えた値(つまり20)を代入する。
$b = $b * 2 ; $bに、現在の$bの値に2を乗じた値(つまり40)を代入する。

3番目の例では、$bを二回使い自分自身を使い、自分自身に値を設定するという形になっています。これは、右項の計算を先に行い、その結果だけに注目し混乱しないようにしましょう。

代入を行う「=」は代入「演算子」と呼ばれることでわかるように、「+」「-」などと同様の演算子であり値を持ちます。

$a + 3が上の例では20という値を持ちますが、同様に$a = 3は3という値を持ちます。代入演算子では常に右項の値がそのまま、式の値となると思って間違いありません。

[使用例]

$b = 4 + ( $a = 3 ) ; $aに3を代入してから、その値に4を加える。その結果、$b には7がセットされる
$d = ( $c = 5 ) ; $cに5を代入してから、同じく $d にも5を代入する
$d = $c = 5; かっこを省いても同じ結果になる。

かっこを省けるのは代入が右結合だからです。

二項代入演算子(binary assignment operator)

$a = $a + 5 のように代入の両側に同じ変数が現れる式は、頻繁に使われます。そのようなケースで、変数の値を変更するために提供される略記法を二項代入演算子といいます。

次の表の左右は同じものを意味しています。

[使用例]

$a += 5; $a = $a + 5;
$b *= 3; $b = $b * 3;
$str . =" "; $str = $str . " ";

つまり、変数の値を式の値によって置き換えるのではなく、変数の元の値を何らかの方法で加工しています。

また、代入演算子同様、二項代入演算子も値を持ちますので次のように書くことも可能です。

[使用例]

$A = 3;
$B = ( $A += 4 );

$A と $B はともに7になります。

オートインクリメント演算子(autoincrement operator)

++と+をふたつ並べたもので、オペランド(値)に1を加算して加算後の値をかえします。

次の2例は、同じ結果になります。

[使用例]

$a += 1; 代入演算子を使った場合
++$a; 上の式と同じ結果を返すオートインクリメント演算子を使った例

上の例では、演算子が変数の前に置かれています。これは前置演算子と言われ、まず変数に1を足してから変数を用います。逆に後ろに置く後置演算子では、変数を使った後に1を足します。

[前置演算子:使用例]

$A = 17;
$E = ++ $A;
$A と $E はともに18になる

[後置演算子:使用例]

$A = 17;
$E = $A ++;
$E は17、しかし$A は18になる

ちなみに、オートインクリメント演算子はオペランドの値を変更するのでオペランドは式ではなくスカラー変数でなければなりません。++ ( $a +$b ) と書いても $a と $b の和より1大きい値を得ることはできません。

オートデクリメント演算子(autodecrement operator)

-を二つ並べた--という演算子で、オートインクリメント演算子とは逆に、オペランド(値)に1を減算して減算後の値を返します。

使い方は、オートインクリメント演算子とほぼ同様です。

[使用例]

$x = 12;  
-- $x; $x は11になる
$y = $x --; $y は11になり $x は10になる

スカラー変数を文字列中に展開する

ダブルクォート文字列では、変数展開(variable interpolation)が行われます。

変数展開はダブルクォート内にある文字列をスキャンしてスカラー変数の名前(ドル記号の付いた文字)を見つけるとその変数をその時点での値に置き換えます。(値が設定されていない場合は、から文字列)

ただし、置き換えた値内にさらにスカラー文字があってもそれ以上の変数展開は行われません。

[使用例]

$a = "red";  
$b = "some text $a"; $b は "some text red になる
$c = "no such varliable $z"; $c は "no such varliable"になる
$d = "hey $b"; $d は "hey some text $a"になる

変数展開させたくない場合は、その部分をシングルクォートで囲むかドル記号の前に逆スラッシュを置きます。

[使用例]

$a = "red";  
$b = "some text " . '$a'; 値は、"some text $a"となる
$c = "some text \$a"; 同じこと

変数名は、意味を成す限りできるだけ長くなるように解釈されます。そのため、変数名に続けて英数字、下線を置くと、Perlはそこまで変数名として解釈します。

変数の値と文字列を連結するには変数の名前をブレースで囲むか、二つの文字列に分解して「.」を用いて連結します。

[使用例]

$red = "pay";
$red_day= "wrong!";
 
$green = "$red_day"; 値は、"wrong!"となる
$green = "${red}_day"; 値は、"pay_day"になる
$d = "$red" . "_day"; これでも同じ結果

変数展開によって得られた文字は大文字小文字の変換を行う逆スラッシュエスケープによって、変換することもできます。

配列演算子による配列の操作

配列関数(array function)と 配列演算子(array operator)は、配列全体に対して作用します。

これらのうち、いくつかのものはリストを返し、返されたリストは、さらに別の配列関数で処理したり、配列変数に代入したりすることができます。

配列代入演算子(array assignment operator)

配列代入演算子は、スカラーの代入演算子と同様に、イコール記号1個で表されます。

代入の対象がスカラー変数か配列変数かに応じて、スカラー代入を行うか配列代入を行うかが決まります。

[使用例]

@red = ( 1 , 2 , 3 ) ; 配列 @red に3要素のリテラルを代入する
@green = @red ; そして、その配列を @green に複写する

スカラー値を配列変数に代入すると、そのスカラー値1個だけを要素とする配列になります。

[使用例]

@blue = 1 ; 数値1は自動的に(1)のというリストに変換される。

配列変数名は、リストリテラルの中で使うことが可能です。

次の例のように、リストの値を評価するときに、変数名をその時点の配列の値で置き換えます。

[使用例]

@red = qw (one two) ;  
@white = ( 4 , 5 , @red , 6 , 7 ) ; 配列 @white は( 4 , 5 , "one" , "two" , 6 , 7 )になる
@white = ( 8 , @black ) ; @white の先頭に8を挿入
@white = ( @black , "ten" ) ; @white の最後に"ten"を追加
  @white は( 8 , 4 , 5 , "one" , "two" , 6 , 7 , "ten" )となる

qw 演算子は空白文字(スペース、改行、Tab )で区切った単語を配列として返します。(リストリテラルで配列を定義するところを、ダブルクォーテーションやシングルクォーテーション、カンマを使わずに書くことができます)

配列は、配列を要素として持つことはできませんので、このような形で挿入された配列の要素は、他の要素と同じレベルにおかれます。

変数のみからなるリストリテラルは、あたかも変数であるかのように扱うことが可能です。

そのようなリストリテラルは代入の左辺に置くことができ、リストリテラル中の各スカラー変数は、右辺のリスト中の対応する値をうけとります。

[使用例]

( $a , $b , $c ) = ( 1 , 2 , 3 ) ; $a に1を、$b に2を、$c に3を代入
( $a , $b ) = ( $b , $a ) ; $a と $b を入れ替える
( $d , @red ) = ( $a , $b , $c ) ; $d に $a を代入、@red に $b と$c を代入
( $e , @red) = @red ; @redの先頭要素を取り除いて$eにセット。
その結果、@red = ($c)、$e = $b となる。

代入の対象になる変数の個数と値の個数が一致しない場合には、(イコールの右側の)値が余れば黙ってそれらは捨てられてしまいます。また、(イコールの左側)変数が余れば、「undef」をセットします。

左辺のリストリテラルの中に配列変数を含める場合は、リストの最後に置くようにしてください。配列の後に、変数を置いた場合は常に「undef」がセットされます。

たとえば(@a , $b) = ( 1 , 2 , "a" , "b") とした場合、右辺のリストリテラルは、そのまま配列@aに挿入されるので、$bはあまりとなって「undef」がセットされます。

配列変数をスカラー変数に代入すると、配列の要素の個数がセットされます。

[使用例]

@red = ( 4 , 5 , 6 ) ; @redを初期化
$a = @red ; $a は配列 @red の要素数、「3」になる

ただし、$aをリストリテラルの($a)と書いた場合、@red の最初の要素が代入されて残りの要素は捨てられます。

[使用例]

( $a ) = @red ; $a は配列 @red の最初の要素、「4」になる

また、配列代入もスカラー代入のときと同じように、連続して代入することが可能です。

[使用例]

@red = @green = ( 1 , 2 , 3 ) ; これで配列 @red と @green に ( 1 , 2 , 3 ) が代入できる
@red = ( @green = ( 1 , 2 , 3 ) ) ; 上と同じ。

スライス(slice)

配列の個々の要素に、アクセスする方法は以前紹介しましたが、同一の配列に含まれる複数の要素に一度にアクセスすることもできます。これを、スライスと言います。

スライスは頻繁に用いられるので、下記のような専用の書き方が用意されています。

[使用例]

@blue [ 0 , 1 ] ; ( $blue [ 0 ] , $blue [ 1 ] )と同じ
@blue [ 0 , 1 ] = @blue [ 1 , 0 ] ; 要素の順を入れ替える
@blue [ 0 , 1 , 2 ] = @blue [ 1 , 1 , 1 ] ; 3つの要素全てを2番目の要素と同じ値にする
@blue [ 1 , 2 ] = ( 9 , 10 ) ; 最後の二つの要素を 9 , 10 にする

スライスの場合は、スカラー変数への代入ではなく配列の一部を配列変数をして扱うので先頭文字は $ ではなく @ になりますので注意してください。
スライスはリテラルリストやリスト値を返す演算子に対しても適用することができます。

[使用例]

@gray = ( qw ( in , out , go , let ) ) [ 2 , 3 ] ; @gray = @dark [ 2 , 3 ] ; となる
@dark = qw ( in , out , go , let ) ;

また、インデックス値は整数の定数だけではなく数を返す式なら、なんでも使用することができます。その場合は式の値に応じて要素が選び出されます。

[使用例]

@gold = ( 7 , 8 , 9 ) ;
$a = 2 ;
 
$b = $gold [ $a ] ; $gold [ 2 ]と同じで9を代入
$c = $gold [ $a - 1 ] ; $c には $gold [ 1 ] の8が代入される
( $c ) = ( 7 , 8 , 9 ) [ $a - 1 ] ; スライスを使っても同じことをする

スライスの場合も添え字に式を使うことができるます。

しかし、スライスの添え字はリストでないといけないのでスカラー式の代わりに配列式を使う必要があります。

[使用例]

@gold = ( 7 , 8 , 9 ) ;
@a = ( 2 , 1 , 0 ) ;
 
@silver = @gold [ @a ] ; @gold [ 2 , 1 , 0 ] や
($gold [ 2 ] , $gold [ 1 ] , $gold [ 0 ] )、( 9 , 8 , 7 )と同じ

配列要素の拡張とアクセス

配列の要素数を超えた要素にアクセスすると、undef を返します。

[使用例]

@gold = ( 7 , 8 , 9 ) ;  
$x = @gold [ 5 ] ; $x は undef になる

現在の配列の末尾を超えて要素に値をセットすると配列は自動的に拡張されます。

ただし、セットする要素と、現在の最後の要素との間に要素があれば自動的にundefがセットされます。

[使用例]

@gold = ( 1 , 2 , 3 ) ;  
$gold [ 3 ] = "light" ; @gold は ( 1 , 2 , 3 , "light" )となる
$gold [ 6 ] = "shadow" ; @gold は ( 1 , 2 , 3 , "light" , undef , undef , "shadow" )となる

配列要素の最後のインデックス値を得るには、「#」を使います。

[使用例]

@palette = ( "black" , "red" , "blue" , "yellow" ) ;  
print $#palette ; 3を表示
print $palette [ $#palette ] ; "yellow" を表示

「-」を使うと配列の要素を最後から数えことになります。

[使用例]

@palette = ( "black" , "red" , "blue" , "yellow" ) ;  
print $palette [ -1 ] ; "yellow" を表示
print $palette [ -2 ] ; "blue" を表示

イメージとしてはこんな感じでしょうか。

インデックス値 -4 -3 -2 -1 0 1 2 3
要素 black red blue yellow black red blue yellow

ポイント

  1. 数値を期待される場合は数値に、文字列を期待される場合は文字列に自動変換。
  2. 変数展開された変数の中に変数が含まれていてもそれ以上は展開されない。
  3. スライスを使い複数の要素に同時にアクセスできる。インデックスは「[ ]」で囲う。
  4. 要素数を超えた配列へのアクセスは、配列を自動で拡張する。
Arry Data Study of CGI Proces

□新着

  • 2016/04/14
    ページ復旧
  • 2007/10/06
    Story Maker始動
  • 2007/06/13
    久々の更新
  • 2007/01/06
    logちょっとバージョンアップ
  • 2006/07/27
    ホームページのPerl 終了

□Topics

  • 2016/04/14
    サイト復旧
  • 2007/10/06
    StoryMaker始動
  • 2007/06/13
    今後にぜひご期待を!
  • 2006/06/26
    今後について
  • 2006/06/15
    環境の変化