関数 オブジェクト渡しとフィルタ

【連載】

PowerShell Core入門 - 基本コマンドの使い方

【第40回】関数 オブジェクト渡しとフィルタ

[2019/02/28 07:00]後藤大地 ブックマーク ブックマーク

  • サーバ/ストレージ

サーバ/ストレージ

オブジェクト渡し

UNIXのシェルではパイプラインを流れるデータは一方通行であり、かつ、データはそのままデータとして流れていく。一方、PowerShell Coreではパイプラインを流れていくのはオブジェクトであり、複数のオブジェクトを流すことができる。ただのデータとして流れていくのではなく、明確に複数のオブジェクトとして流れていくという違いがある。

これはつまり、データが明確に区切りのある対象として送信されてくるということだ。PowerShell Coreではパイプラインで送られてくるオブジェクトごとに処理を記述できるようになっている。

PowerShell Coreは明示的にシェルやコマンドプロンプトに近いニュアンスを実現するように設計されているが、背後にはオブジェクト指向プログラミング言語の考え方が取り込まれており、細かくなってくるとオブジェクト指向言語として考えた方が理解しやすくなる。

こうした特徴を備えているため、PowerShell Coreの関数は機能的に強力だ。関数の状態でパイプラインを流れてくる複数のオブジェクトを処理するコードが書けるようになっている。今回はこの書き方を取り上げる。

関数でのオブジェクト渡し

関数でオブジェクトを処理する場合、Begin、Process、Endという3つのブロックについて知る必要がある。

オブジェクト渡しで使われるブロック

function 関数名 {
    begin { 処理 }
    process { 処理 }
    end { 処理 }
}

ブロックはそれぞれ次の役割を持っている。

ブロック 内容
Begin 関数の開始時に1回だけ実行される
Process パイプラインを流れてくるオブジェクトごとに1回ずつ実行される。パイプラインを流れてくるオブジェクトは$_に割り当てられる
End 関数の終了時に1回だけ実行される。Processブロックが使われていない場合、$inputからすべてのオブジェクトにアクセスできる。Processブロックが使われている場合、$inputには何も入っていない

BeginブロックとEndブロックは名前のとおり関数が実行される最初の段階と最後の段階で1回だけ実行される。Processブロックはオブジェクトの入力があるたびに実行される。つまり、パイプラインを経由して渡ってくるデータを処理する場合、Processブロックに処理を書けばよいことになる。

Processブロックでは$_という自動変数に渡ってくるオブジェクトが代入される仕組みになっている。つまり、Processブロックで$_を使って処理を書くというのが、Processブロックでの主なコーディング作業ということになる。

たとえば次のサンプルは1から5までの整数を作成した関数に流し込んだ場合の実行例だ。Processブロックが入力される数字の分だけ動作していることがわかる。

Processブロックが入力されてくるオブジェクトの分だけ動作していることがわかる

PS /Users/daichi> function Do-PipelineTest   
>> {
>>     begin {"begin: $input"}
>>     process {"process: $_"}
>>     end {"end: $input"}
>> }
PS /Users/daichi> 1,2,3,4,5 | Do-PipelineTest
begin: 
process: 1                    
process: 2                    
process: 3                
process: 4
process: 5
end: 
PS /Users/daichi>

Endブロックでは$inputという変数が扱えることも覚えておきたい。関数の中でProcessブロックが使われていない場合、Endブロックで$inputという変数から入力されてくるすべてのオブジェクトにアクセスできる。

Processブロックがない場合、Endブロックで$inputを使って入力されたオブジェクトにアクセスできる

PS /Users/daichi> function Do-PipelineTest   
>> {
>>     begin {"begin: $input"}
>>     end {"end: $input"}  
>> }                      
PS /Users/daichi> 1,2,3,4,5 | Do-PipelineTest
begin: 
end: 1 2 3 4 5                
PS /Users/daichi>

ただし、この機能はProcessブロックが存在する場合には機能しない。次のようにProcessブロックの中で$_を使っていないとしても、Processブロックが存在するとEndブロックで$inputにアクセスしてもなにも表示されなくなる。

Processブロックが存在する場合、Endブロックで$inputにアクセスしても何も表示されない

PS /Users/daichi> function Do-PipelineTest   
>> {
>>     begin {"begin: $input"}
>>     process {"process: "}  
>>     end {"end: $input"}
>> }
PS /Users/daichi> 1,2,3,4,5 | Do-PipelineTest
begin: 
process:                      
process:                    
process:                  
process: 
process: 
end: 
PS /Users/daichi>

最低でもProcessブロックでオブジェクトごとの処理を記述する、ということを覚えておきたい。

フィルタ

PowerShell Coreには関数の特別なスタイルとしてフィルタという機能が用意されている。フィルタは基本的に次のように定義する。

フィルタの書き方

filter 関数名
{
    処理
}

これは要するに次のように記述したのと同じだ。フィルタとして定義することでどのように機能するのかがよりわかりやすくなる。

関数でフィルタと同じ書き方をした場合

function 関数名
{
    Process
    {
        処理 
    }
}

フィルタを使って処理を書くと、たとえば次のような感じになる。

フィルタを使った場合

PS /Users/daichi> filter Do-FilterTest([switch]$upper,[switch]$lower)
>> {
>>     if ($upper) {$_.ToUpper()}
>>     elseif ($lower) {$_.ToLower()}
>>     else {$_}
>> }
PS /Users/daichi> "a","B","c","D","e" | Do-FilterTest                
a   
B                                
c                                    
D               
e   
PS /Users/daichi> "a","B","c","D","e" | Do-FilterTest -upper
A
B
C
D
E
PS /Users/daichi> "a","B","c","D","e" | Do-FilterTest -lower
a
b
c
d
e
PS /Users/daichi>

上記サンプルではパラメータとして-upperと-lowerが指定できるようになっており、-upperが指定されると文字列を大文字にして、-lowerが指定されると文字列を小文字にして出力が行われる。何も指定がなければそのまま出力される。

フィルタとして定義されているので、入力されるオブジェクトに対して何らかの処理を行うものだ、ということがよくわかる。

パラメータとオブジェクト

これまで3回に渡ってPowerShell Coreの関数を取り上げてきた。これで関数の名前の付け方、各種パラメータ(名前付きパラメータ、ポジションパラメータ、スイッチパラメータ、パラメータ渡し)、オブジェクト渡し、フィルタを説明したことになる。あとは関数におけるスコープあたりを取り上げれば、PowerShell Coreの提供している関数の主な機能は網羅することになる。

PowerShell Coreでは関数はコマンドレットに相当するような重要な機能である。関数が定義できるようになると、再利用性の高いコードを記述しやすくなる。PowerShell Coreの関数はシェルの関数とも汎用プログラミング言語の関数ともちょっと違った側面を持っているので、そのあたりも含めていろいろ試してもらえればと思う。

参考資料

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

【連載】RPA入門 - ツールで学ぶ活用シーン

【連載】RPA入門 - ツールで学ぶ活用シーン

AIには、ルールベース、機械学習、深層学習(ディープラーニング)の3つのレベルがあり、レベルが上がるに連れてより高度な人工知能を実現しますが、AIのスピンオフという位置付けで、Digital Labor(仮想知的労働者)によるホワイトカラー業務の自動化を実現するRPAが注目されています。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で IT Search+ の人気記事をお届けします

会員登録(無料)

注目の特集/連載
知りたい! カナコさん 皆で話そうAIのコト
教えてカナコさん! これならわかるAI入門
対話システムをつくろう! Python超入門
Kubernetes入門
AWSで作るクラウドネイティブアプリケーションの基本
ソフトウェア開発自動化入門
PowerShell Core入門
徹底研究! ハイブリッドクラウド
[解説動画] Googleアナリティクス入門講座
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

ページの先頭に戻る