Windows PowerShell 入門(8)-関数編3
この連載では、Microsoftが提供している新しいシェル、Windows PowerShellの使い方を解説します。今回は、フィルタ、スクリプトブロック、変数のスコープについて取り上げます。
はじめに
この連載では、Microsoftが提供している新しいシェル「Windows PowerShell」の使い方を解説します。今回は、フィルタ、スクリプトブロック、変数のスコープについて説明します。
対象読者
- Windows PowerShellでコマンドレット操作ができる方
- 何らかのプログラミング経験があればなお良い
必要な環境
- Windows PowerShell
フィルタ
PowerShellには、関数とは別にパイプを通して受け取ったオブジェクトを処理するフィルタと呼ばれるものがあります。書式は関数とほぼ一緒なのですが、functionの代わりにfilterキーワードを使用します。
filter <フィルタ名> (引数) {実行するスクリプト}
関数と同様、結果をreturnで返すことも可能です。
フィルタの利用例
唐突ですが、ここで問題です。「現在稼働しているサービス一覧を取得してください」と言われたらどうしますか?
解答例を示します。
PS > Get-Service | Where { $_.Status -eq "Running" }
Status Name DisplayName
------ ---- -----------
Running AeLookupSvc Application Experience
Running AppHostSvc Application Host Helper Service
Running AudioEndpointBu... Windows Audio Endpoint Builder
Running Audiosrv Windows Audio
Running BFE Base Filtering Engine
:
: ≪長いので省略≫
:
Get-ServiceコマンドレットとWhereを使用してステータスが"Running"のものをフィルタしています。この $_.Status -eq "Running" はフィルタ化することが可能です。
では、フィルタ名を StsRunning としてフィルタを作成してみましょう。
PS > filter StsRunning {
>> if ( $_.Status -eq "Running" )
>> {
>> return $_
>> }
>> }
>>
こうして作成したフィルタの使用方法は簡単で、パイプの後ろに記述するだけです。
PS > Get-Service | StsRunning Status Name DisplayName
------ ---- -----------
Running AeLookupSvc Application Experience
Running AppHostSvc Application Host Helper Service
Running AudioEndpointBu... Windows Audio Endpoint Builder
Running Audiosrv Windows Audio
Running BFE Base Filtering Engine
このように、よく使用するフィルタ条件は、専用のフィルタを作成しておくと便利です。
なお、フィルタはコンソール上で作成すると、PowerShell終了時に消滅してしまうので、プロファイルに登録することをお奨めします(連載第7回の「関数をプロファイルに追加する」参照)。
関数とフィルタの違いをまとめると、次のとおりです。
- 関数は、パイプで受け取ったオブジェクトを一度に処理する
- フィルタは、パイプで受け取った個々のオブジェクトごとに実行する
スクリプトブロック
「スクリプトブロック」とは、他の言語で言う匿名関数やラムダ式に相当するものです。PowerShellにおいては中括弧{}で囲まれたスクリプトコードに過ぎません。
例えば
PS > 1..10 | foreach { Write-Host $_ }
と記述したときの、{ Write-Host $_ }はスクリプトブロックです。
スクリプトブロックを変数に代入する
スクリプトブロックは、変数に代入することもできます。
例えば下記は、変数$aを3倍するというスクリプトブロックを変数$sに代入したことになります。
PS > $s = { $a * 3 }
スクリプトブロックを実行する
では、スクリプトブロックを実行するにはどうすれば良いでしょうか?
PS > $s
上記のように変数名を入力して[Enter]を押すだけでは実行することができません。
スクリプトブロックを実行するには、下記のように &演算子を使用します。
PS > $a =2
PS > & $s
6
スクリプトブロックではparamによる引数の受け取りが可能です。下記のスクリプトブロックは、paramで引数を1つ受け取り、引数を3倍します。
PS > $script = { param($a); $a * 3 }
実行方法は、先ほど説明したように&演算子を使用して変数名を指定し、その後に引数として渡す値を記述します。
PS > & $script 5
15
もう1つ、$argsによる値の受け取りも可能です。先ほどのスクリプトブロックを$argsで書き換えてみたのが下記です。
PS > $script = { $args[0] * 3 }
実行方法は、paramのときと同様です。
PS > & $script 5
15
変数のスコープ
まずは、下記スクリプトで変数のスコープについてみていきたいと思います。
$a = 3 function Sample1
{
Write-Host "1)変数`$a=$a"
$a = 5
Write-Host "2)変数`$a=$a"
} #関数 sample1を実行
Sample1
Write-Host "3)変数`$a=$a"
このスクリプトを実行すると結果は下記のようになります。
PS C:\Work> ./Scope1.ps1
1)変数$a=3
2)変数$a=5
3)変数$a=3
この動作について図で解説します。

スクリプトの1行目で変数$aを作成し、3を代入しています。この変数はスクリプト内で有効です(1行目から12行目までがこの変数のスコープ。スクリプトスコープという)。
次に、11行目で関数Sample1を呼び出します。この呼び出しにより5行目が実行され、ここの変数$aでは1行目で代入した値「3」が表示されます。
次に6行目で変数$aに「5」を代入していますが、この変数$aは1行目で作成した変数とは別のものです。関数Sample1内でのみ有効で、生存期間は6行目から7行目までとなります。これをローカル変数と呼びます。
関数Sample1の実行が終わり、最後に12行目が実行されるわけですが、ここの変数$aは1行目で作成した変数$aであり、結果として「3」が表示されます。
以上より、次のことが分かります。
- 関数の外側で作成した変数は、スクリプトファイル内すべてが有効範囲である。
- 関数内で作成した変数は、関数内のみが有効範囲である。
- 関数の外で作成された変数と、関数内で作成した変数が同一名の場合は関数内で作成した変数が優先されるが、スクリプトスコープを持つ変数を上書きしない。
スクリプトスコープを持つ変数を参照する
先ほどの例で、$aという同じ名前でスコープの異なる2つの変数を使用しました。関数内でローカル変数$aが優先されることは説明したとおりです。
では、ローカル変数$aが優先されている状況下の中で、スクリプトスコープを持つ$aを参照するにはどうすれば良いでしょうか? この場合は、script修飾子を使用します。
例を示します。
$a = 3 function Sample2
{
Write-Host "1)変数`$a=$a"
$a = 5
Write-Host "2)変数`$a=$a"
Write-Host "3)変数`$a=$script:a"
$script:a = 7
Write-Host "4)変数`$a=$script:a"
Write-Host "5)変数`$a=$a"
} #関数 sample2を実行
Sample2
Write-Host "6)変数`$a=$a"
このスクリプトの実行結果は下記の通りです。
PS C:\Work> ./Scope2.ps1
1)変数$a=3
2)変数$a=5
3)変数$a=3
4)変数$a=7
5)変数$a=5
6)変数$a=7
このように変数名が重複する場合に、スクリプトスコープを持つ変数を参照するには、$script:aと、キーワードscriptを付加し、スクリプトスコープの変数への参照であることを明示します。
また、スクリプトスコープの変数へ値を代入してもローカル変数の値は影響を受けないこと、関数を抜けた後の変数の値が変更されていることも確認してください。
ポイントは次の2点です。
- 関数内でスクリプトスコープを持つ変数へのアクセスは
script修飾子を使用する。 script修飾子を使用して値を書き換えても、同一名称のローカル変数へは影響しない。
少し複雑なサンプルですが、ぜひ実際に実行して、ローカル変数とスクリプトスコープを持つ変数の違いを理解してください。
プライベートスコープ
変数のスコープの種類には、プライベートスコープもあります。下記スクリプトで説明します。
$a = 3 function funcA
{
Write-Host "2)$a"
$a = "7"
Write-Host "3)$a"
funcB
} function funcB
{
Write-Host "4)$a"
} Write-Host "1)$a"
funcA
Write-Host "5)$a"
このスクリプトには2つの関数があり、最初にfuncAを呼び出し、funcAの中からfuncBを呼び出しています。またソース内での1)~5)は分かりやすいように実行順を示しています。
このスクリプトの実行結果は下記の通りです。
PS C:\Work> ./Scope3.ps1
1)3
2)3
3)7
4)7
5)3
このスクリプトの動作について図で説明します。

1行目の変数$aはスクリプトスコープを持つ変数となるので、有効期間は赤線の通りでスクリプトファイルの最後までです。
次に6行目の変数$aですが、この変数はローカル変数となりfuncAが有効期間です。
さらに、この関数funcAはfuncBを呼び出しており、funcAで作成したローカル変数$aの有効期間は青線で示した箇所、つまりfuncBまでおよびます。
では、funcA内だけで有効なローカル変数を作成したい場合は、どうすれば良いでしょうか?
これを実現するにはprivate修飾子を使用します。
下記は「Scope3.ps1」をprivate修飾子を使用して書き換えたものです。funcAのローカル変数のスコープがfuncBに及ばないようにしています(6行目でpraivateキーワードを付加しています)。
$a = 3 function funcA
{
Write-Host "2)$a"
$private:a = "7"
Write-Host "3)$a"
funcB
} function funcB
{
Write-Host "4)$a"
} Write-Host "1)$a"
funcA
Write-Host "5)$a"
このスクリプトの実行結果は下記の通りです。
PS C:\Work> ./Scope4.ps1
1)3
2)3
3)7
4)3
5)3
「Scope4.ps1」でのスコープを図で見てみましょう。

privateキーワードを使用したので、funcAのローカル変数$aのスコープは青線の部分となります。
グローバルスコープ
最後にグローバルスコープを持つ変数について説明したいと思います。グローバル変数は、スクリプトファイルを超えてスコープを持つ変数です。
下記スクリプトで実験してみたいと思います。
$global:glb_a = 3 function funcA
{
Write-Host "2)$glb_a"
} Write-Host "1)$glb_a"
funcA
Write-Host "3)$glb_a"
グローバル変数を作成するには、1行目のようにglobal修飾子を使用します。
このスクリプトの実行結果は下記の通りです。
PS C:\Work> ./scope5.ps1
1)3
2)3
3)3
スクリプト内で$glb_aというグローバル変数を作成しました。最初に説明したように、グローバル変数はスクリプトファイルを超えてスコープを持つので、スクリプトの実行後にコマンドラインで変数を参照することが可能です。
PS C:\Work> $glb_a
3
ではグローバル変数のスコープを図で見てみましょう。

グローバル変数のスコープは、「Scope5.ps1」が呼び出された後(水色の矢印)スクリプトが終わるまで有効です。
さらに、スクリプトが終了し、コンソールウィンドウに戻った後(赤の点線)もグローバル変数は生存し続けます。
結果として、コマンドラインで$glb_aを確認できたというわけです。
まとめ
今回は、次の3点について説明しました。
- フィルタ
- スクリプトブロック
- 変数のスコープ
変数のスコープは説明が長くなってしまいましたが、スクリプト開発を行う上で非常に重要な概念ですので、ぜひ覚えてもらいたいと思います。
次回は、エラーの取り扱いについて説明します。
Windows PowerShell 入門(8)-関数編3的更多相关文章
- Windows PowerShell 入門(7)-関数編2
この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.前回に引き続きPowerShellにおける関数の取り扱いとして.変数と関数のスコ ...
- Windows PowerShell 入門(3)-スクリプト編
これまでの記事 Windows PowerShell 入門(1)-基本操作編 Windows PowerShell 入門(2)-基本操作編 2 対象読者 Windows PowerShellでコマンド ...
- Windows PowerShell 入門(2)-基本操作編 2
前回に引き続きMicrosoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.基本操作編第2弾の今回は.パイプの使用方法を中心としたコマンドレットの操作方 ...
- Windows PowerShell 入門(6)-関数編1
この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.今回は.関数の作成基礎と引数.戻り値.Switchパラメータについて説明します. ...
- Windows PowerShell 入門(10)-デバッグ編
対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell デバッグメッセージの出力 Po ...
- Windows PowerShell 入門(9)-エラー編
対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell エラーをリダイレクトする リダ ...
- Windows PowerShell 入門(4)-変数と演算子
Windows PowerShellにおける変数と演算子の使用方法について学びます.今回は代表的な演算子として.算術演算子.代入演算子.論理演算子.比較演算子.範囲演算子.置換演算子.ビット演算子.型 ...
- Windows PowerShell 入門(1)-基本操作編
Microsoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.インストール.起動終了方法.コマンドレット.命名規則.エイリアス.操作方法の調べ方について ...
- Windows PowerShell 入門(5)-制御構文
Windows PowerShellにおける制御構文について学びます.数ある制御構文の中でもSwitch文は.他の言語に比べ豊富な機能が用意されています. 対象読者 Windows PowerShel ...
随机推荐
- o(1), o(n), o(logn), o(nlogn)
转自:https://blog.csdn.net/Mars93/article/details/75194138 在描述算法复杂度时,经常用到o(1), o(n), o(logn), o(nlogn) ...
- go build 和 go run区别
- JVM jinfo命令(Java Configuration Info) 用法小结
简介 jinfo是jdk自带的命令,可以用来查看正在运行的Java应用程序的扩展参数,甚至支持在运行时,修改部分参数. 通常会先使用jps查看java进程的id,然后使用jinfo查看指定pid的jv ...
- BFC规范
BFC规范 BFC规范是什么? BFC规范也叫块级格式化上下文.是指一个独立的容器. 如何触发BFC? 我们可以通过一下几种方式触发BFC 1.通过浮动触发:float(除none) 2.通过绝对\固 ...
- linux 精简开机自启动
centos7 精简开机自启动 ntsysv rsyslog crond sshd network
- 常见排序算法之python实现
冒泡排序 简介 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是重复地进行直到没有再需要交 ...
- JS定义函数
一.定义函数的方法 (1)函数声明 (2)函数表达式 二.函数声明方法定义函数 function functionName(arg0, arg1, arg2) { // 函数体 } (1)FireFo ...
- HTML 实例学习(基础)
1.HTML <html> 标签 注意:对于中文网页需要使用 <meta charset="utf-8"> 声明编码,否则会出现乱码.有些浏览器会设置 GB ...
- RMQ st算法 区间最值模板
#include<bits/stdc++.h> ; ; int f[N][Logn],a[N],lg[N],n,m; int main(){ cin>>n>>m; ...
- Unet网络
近期利用遥感影像进行路网提取,利用Unet网络进行图像分割 介绍如下: U-net网络非常简单,前半部分作用是特征提取,后半部分是上采样.在一些文献中也把这样的结构叫做编码器-解码器结构.由于此网络整 ...