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をコピーしました