Powershellの関数(Function)の使い方

Powershell

Powershellでは関数の利用が可能です。再用可能なコードなどを関数化しておくことで、コードの見通しが良くなり、保守性も向上します。

基本的な使い方

まずは基本的な使い方を紹介します。

基本構文

Functionの定義は以下のように行います。

Function 関数名(引数) {
  処理
}

また、定義した関数は「関数名 引数」の形で呼び出します。以下、非常に簡単なSayHello関数に引数を渡す例です。

Function SayHello($name){
    Write-Host "Hello $name!"
}

SayHello "Powershell" # Hello関数に"Powershell"という文字列を渡す

# 出力結果:Hello Powershell!

関数に渡す引数について

関数の引数はParam()を利用することができます。

Function ArgTest {
    Param(
        $Arg1,  # 改行する場合はカンマを忘れずに
        $Arg2
    )
    Write-Host "引数1:$Arg1 引数2:$Arg2"
}

ArgTest -Arg1 "AAA" -Arg2 "BBB"  
# 出力結果: 引数1:AAA 引数2:BBB

その他引数のオプションなども利用可能です。

高度な関数

Powershellでは関数をコマンドレットのように動作させる機能があります。コンパイルする必要がなく、手軽にコマンドレットライクな関数を書くことが可能となっています。

定義方法

関数を高度な関数として定義するには、Functionの中に [CmdletBinding()] 属性を追加します。

Function AdvancedFunction {
  [CmdletBinding()]
  Param()
  Begin{}
  Process {}
  End{}
}

[CmdletBinding()]属性のオプションについて

[CmdletBinding()]属性には多数のオプションがあります。オプションは()内に記載します。以下オプション一覧とざっくりとした説明です。

ConfirmImpact=<String>-Confirmパラメーターが利用可能になります。また、ユーザー設定変数である$ConfirmPreferenceの値以上である場合、確認プロンプトが表示されます。
DefaultParameterSetName=<String>既定のパラメーターセット名を定義します。パラメータセット名を省略した場合、本パラメータセット名が利用されます。
HelpURI=<URI>オンラインヘルプのURIを定義します。
SupportsPaging=<Boolean>-First / -Skip / -IncludeTotalCountパラメータが利用可能になります。
SupportsShouldProcess=<Boolean> -Confirm / -WhatIfパラメーターが利用可能になります。
PositionalBinding=<Boolean>位置指定パラメーターを有効にすることができます。

詳細は以下公式ページにて確認してください。

Powershell関数のreturnについて

PowerShellにおける関数のreturnについて、他のプログラミング言語とは異なる挙動となっているため、注意が必要となります。

具体的には関数内で標準出力が伴う処理を行うと、return以前の出力も戻り値となり呼び出し元に出力されてしまいます。以下関数化するまでもない処理ですが、フォルダを作成する関数を例に説明します。

# MakeDirectoryTest.ps1
function MakeDirectory{
    param(
        $Path
    )
    mkdir $path
    return $true
}
MakeDirectory .\test
PS C:\> .\MakeDirectoryTest.ps1 ディレクトリ: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/03/30 22:37 test True

mkdirの標準出力も表示されました。関数の実行結果をGetTypeメソッドで確認してみると、returnではBoolenを返しているにも関わらず、オブジェクト配列で返ってきます。

PS C:\> $Result = MakeDirectory .\test2 PS C:\> $Result.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array

配列の中身を見てみると、1つの目の要素はDirectoryInfoとして、二つ目の要素ではBooleanとして格納されています。

PS C:\> $Result[0].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DirectoryInfo System.IO.FileSystemInfo PS C:\> $Result[1].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Boolean System.ValueType

この挙動を理解していれば問題ないですが、意図せぬ結果とならぬよう注意が必要です。

回避するには標準出力が伴う処理は[void]にキャストするか、Null破棄を行う必要があります。

# MakeDirectoryTest2.ps1
function MakeDirectory{
    param(
        $Path
    )
    [void](mkdir $path)  # voidにキャスト
    # またはmkdir $path > $null として標準出力のNull破棄を行う
    return $true
}
MakeDirectory .\test
# MakeDirectoryTest2.ps1
function MakeDirectory{
    param(
        $Path
    )
    [void](mkdir $path)  # voidにキャスト
    # またはmkdir $path > $null として標準出力のNull破棄を行う
    return $true
}
MakeDirectory .\test
PS C:\> .\MakeDirectoryTest2.ps1 True

参考サイト

以下記事を参考にさせていただきました。

まとめ

冒頭にも書きましたが、再利用可能な処理については関数化することで、可読性・保守性が向上します。関数の特性について理解した上で積極的に利用してみてください。

コメント

タイトルとURLをコピーしました