特集
» 2007年09月20日 00時00分 公開

Windows PowerShellコマンド&スクリプティング入門:PowerShellスクリプティングの第一歩(後編) (4/5)

[山田祥寛,著]

 関数とは、呼び出し元から渡された値をなにかしら決められた方法で処理(演算)し、その結果を呼び出し元に返すための仕組みだ。スクリプト、対話シェルを問わず、よく利用する処理は関数として定義しておくことで、同じようなコードを記述する必要がなくなるので、処理を簡潔に記述することができる。ほかの言語をご存じの方ならば、おなじみの機能であるが、PowerShellでももちろん関数を定義することが可能だ(*)。

* ちなみに、関数はユーザーが自前で定義するばかりでなく、PowerShell標準で提供されているものも多く存在する(例えば、前編で紹介したmoreも、その実体は関数である)。現在登録されている関数の一覧を参照するには、「Get-ChildItem Function:」とすればよい。


関数の基本

 まずは、ごく基本的な関数の例として、与えられた引数$width(底辺)、$height(高さ)に従って三角形の面積を求めるTriangle関数を定義し、これを利用するコードを見てみることにしよう(注:面積=底辺×高さ÷2)。以下が、そのコードだ。

function Triangle([double] $width=1, [double] $height=1) {
  return $width * $height / 2
}

Triangle 2 6  # 結果は 6 と表示される ……(1)

与えられた引数$width/$heightに基づいて三角形の面積を求めるTriangle関数(Triangle.ps1)

 関数の構文規則については、すでになにかしらの言語を学んだことがある方ならば容易に理解できるだろうが、一応、以下にまとめておく。

function 関数名 [(引数[=デフォルト値],...)] {
  関数の本体
  [return 戻り値]
}

 引数が存在しない(あるいは引数名を明示的に宣言しない)場合には、関数名の後ろのカッコは省略できる。また、ここでは仮引数に対して明示的にデータ型を指定しているが、前述したように、PowerShellはデータ型の宣言を強制しない言語である。従って、データ型の検査が不要である場合には、単に

function Triangle($width=1, $height=1) {

としても構わない。

 宣言した関数を呼び出しているのは、リスト内の(1)の部分である。ほかのプログラミング言語に慣れている方ならば、思わず

Triangle(2,6)

のように書きたくなるかもしれないが、これはできないので注意が必要である。というのも前述したように、PowerShellではカンマ演算子によって配列を表すことができる。つまり上のような記述では、「2、6を要素に持つ配列型の引数を与える」という意味になってしまう(もしもそういう意味で記述しているならば、これは構文的に誤りではないが)。引数は、

関数名 引数1 引数2 〜

のように、空白区切りで記述しなければならないことを覚えておこう。

 またPowerShellでは、以下のように引数を明示的に指定した呼び出しも可能である。

Triangle -width 2 -height 6

 この形式では、引数の指定に順番は関係ないので、

Triangle -height 6 -width 2

のように記述しても構わないし、

Triangle -height 6 -width 2 -nothing 0

のように、合致する仮引数が関数側に存在しない引数を指定することもできる(その場合には無視される)。しかし、同じ引数名を複数回指定した場合にはエラーとなる。

function Triangle([double] $width=1, [double] $height=1) {
  return $width * $height / 2
}

Triangle -width 2 -width 6

PS > ./Triangle.ps1
Triangle : パラメータ 'width' が複数回指定されているため、パラメータをバインドできません。複数の値を受け入れるパラメータに対して複数の値を指定するには、配列構文を使用してください。たとえば、"-parameter value1,value2,value3" と指定します。

[コラム]スクリプトのパラメータ宣言

 引数を介することで、関数に対してパラメータを引き渡すことができるのと同様、スクリプト・ファイルに対しても、Param命令を利用することで、外部から引き渡すためのパラメータを明示的に宣言することが可能だ。以下は、スクリプト側で参照可能な$nameパラメータを宣言する例である。

Param([string] $name)
Write-Output "こんにちは、 $name さん!"

パラメータを明示的に宣言されたスクリプト・ファイル(Hello.ps1)

 このように宣言されたスクリプト・ファイルを呼び出すには、以下のように記述する。

PS > ./Hello.ps1 "山田"
こんにちは、 山田 さん!
PS > ./Hello.ps1 -name "山田"
こんにちは、 山田 さん!


名前付き引数と名前なし引数

 さて、先ほどは関数側で明示的に仮引数名を宣言する例について見てみた(これを「名前付き引数」と呼ぶ)。しかしPowerShellでは、仮引数を明示的に宣言しない、「名前なし引数」を利用することも可能だ。例えば、先ほどのTriangle関数を名前なし引数を使って定義すると、以下のように記述できる。

function Triangle {
  return $Args[0] * $Args[1] / 2
}

先ほどのTriangle関数を名前なし引数を使って書き直した例

 このように、名前なし引数を利用した場合には、引数は自動変数$Argsを介して取得することができる。自動変数とは、PowerShellによって自動的に値が設定されている変数のことで、あらかじめ用途が予約されていることから「予約変数」とも呼ぶ。例えば前回紹介した「$_」(パイプライン経由で渡されたオブジェクト)も自動変数の一種である。

 関数に渡された名前なし引数は自動変数$Args(配列)に登録されるので、あとは「$Args[0]」のように指定することで、与えられた引数値にアクセスすることができる。なおJavaScriptなどの言語に慣れている方は、自動変数$Argsには関数に渡されたすべての引数値(名前付き引数/名前なし引数の双方)が含まれるように思われるかもしれないが、PowerShellではあくまで名前なし引数だけしか含まれない。細かい点ではあるが、意外と間違えやすいポイントなので注意してほしい。

変数のスコープ

 関数が登場すると、いよいよ意識しなければならなくなるのが変数のスコープだ。スコープとは、プログラム中での変数の有効範囲のことである。まずすべてのスコープから参照できる「グローバル・スコープ」と、関数内部でのみ有効な「ローカル・スコープ」については、読者諸兄もよくご存じであろう。しかしPowerShellでスクリプトを記述する場合、もう1つ、「スクリプト・スコープ」の存在を意識しておく必要がある。

 スクリプト・スコープとはその名のとおり、スクリプト・ファイル内のすべてのスコープから参照可能なスコープである。スクリプト内のグローバル・スコープであるといってもよいだろう。スクリプト内で処理を完結している限り、このスクリプト・スコープを意識する局面はさほどないのであるが、例えば以下のようなケースを見てみよう。Triangle.ps1は先ほど紹介したTriangle関数を定義したスクリプト・ファイルだ。

PS > ./Triangle.ps1
PS > Triangle 2 6
用語 'Triangle' は、コマンドレット、関数、操作可能なプログラム、またはスクリプト ファイルとして認識されません。用語を確認し、再試行してください。
発生場所 行:1 文字:9

スクリプト・スコープの確認

 これは、Triangle.ps1の中で定義されたTriangle関数は、スクリプト・スコープに属するため、スクリプト外のスコープからは参照できないことから起こる挙動だ。

 PowerShellでは、変数や関数は現在のスコープで作成されるのがデフォルトの挙動であるが、もしもスクリプト・ファイル内で宣言された関数をスクリプト外から参照したければ、Triangle関数の定義を以下のように修正すればよい。

function global:Triangle([double] $width=1, [double] $height=1) {
  return $width * $height / 2
}

所属スコープを明示的に宣言したTriangle関数(Triangle.ps1)

 「global:」はスコープ修飾子と呼ばれるもので、関数や変数のスコープを強制的に変更するための役割を持つ。これにより、本来スクリプト・スコープに属するはずのTriangle関数を、強制的にグローバル・スコープに登録している。

 果たして、この状態でもう一度、対話シェル上から以下のコードを実行してみると、正しくTriangle関数を呼び出せることが分かる。

PS > ./Triangle.ps1
PS > Triangle 2 6
6

スコープ修飾子の挙動を確認する

 このスコープ修飾子は、変数に対しても「$global:x」(グローバル変数)、「$script:x」(スクリプト変数)、「$local:x」(ローカル変数)のように指定することができる。

[コラム]プロファイルの活用

 PowerShellではプロファイルという機能を提供しており、起動時に決められたスクリプトを読み込み、実行することができる。よく使う関数やエイリアスなどは、このプロファイル機能を利用して登録しておくと便利だろう。

 プロファイルの利用方法は簡単で、「C:\WINDOWS\SYSTEM32\windowspowershell\v1.0」フォルダ配下にprofile.ps1という名前でスクリプト・ファイルを配置しておくだけでよい。これによってPowerShellの起動時にProfile.ps1が自動実行され、(例えば)関数やエイリアスの登録を行うことができる(*)。

* なお、profile.ps1の内容はすべてグローバル・スコープで登録される。従って、本文の例のように明示的にスコープ修飾子によるスコープ宣言を行う必要はない。


 ちなみに「C:\WINDOWS\SYSTEM32\windowspowershell\v1.0」フォルダに配置されたprofile.ps1はすべてのユーザーに対して有効なグローバル・プロファイルとして扱われるが、ユーザー単位にプロファイルを区別したいという場合には「C:\Documents and Settings\<ユーザー名>\My Documents\WindowsPowerShell」フォルダにprofile.ps1を配置する必要がある。


Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。