この連載では、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

変数のスコープ

 まずは、下記スクリプトで変数のスコープについてみていきたいと思います。

Scope1.ps1
$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修飾子を使用します。

 例を示します。

Scope2.ps1
$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修飾子を使用して値を書き換えても、同一名称のローカル変数へは影響しない。

 少し複雑なサンプルですが、ぜひ実際に実行して、ローカル変数とスクリプトスコープを持つ変数の違いを理解してください。

プライベートスコープ

 変数のスコープの種類には、プライベートスコープもあります。下記スクリプトで説明します。

Scope3.ps1
$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が有効期間です。

 さらに、この関数funcAfuncBを呼び出しており、funcAで作成したローカル変数$aの有効期間は青線で示した箇所、つまりfuncBまでおよびます。

 では、funcA内だけで有効なローカル変数を作成したい場合は、どうすれば良いでしょうか?

 これを実現するにはprivate修飾子を使用します。

 下記は「Scope3.ps1」をprivate修飾子を使用して書き換えたものです。funcAのローカル変数のスコープがfuncBに及ばないようにしています(6行目でpraivateキーワードを付加しています)。

Scope4.ps1
$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のスコープは青線の部分となります。

グローバルスコープ

 最後にグローバルスコープを持つ変数について説明したいと思います。グローバル変数は、スクリプトファイルを超えてスコープを持つ変数です。

 下記スクリプトで実験してみたいと思います。

Scope5.ps1
$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的更多相关文章

  1. Windows PowerShell 入門(7)-関数編2

    この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.前回に引き続きPowerShellにおける関数の取り扱いとして.変数と関数のスコ ...

  2. Windows PowerShell 入門(3)-スクリプト編

    これまでの記事 Windows PowerShell 入門(1)-基本操作編 Windows PowerShell 入門(2)-基本操作編 2 対象読者 Windows PowerShellでコマンド ...

  3. Windows PowerShell 入門(2)-基本操作編 2

    前回に引き続きMicrosoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.基本操作編第2弾の今回は.パイプの使用方法を中心としたコマンドレットの操作方 ...

  4. Windows PowerShell 入門(6)-関数編1

    この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.今回は.関数の作成基礎と引数.戻り値.Switchパラメータについて説明します. ...

  5. Windows PowerShell 入門(10)-デバッグ編

    対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell デバッグメッセージの出力 Po ...

  6. Windows PowerShell 入門(9)-エラー編

    対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell エラーをリダイレクトする リダ ...

  7. Windows PowerShell 入門(4)-変数と演算子

    Windows PowerShellにおける変数と演算子の使用方法について学びます.今回は代表的な演算子として.算術演算子.代入演算子.論理演算子.比較演算子.範囲演算子.置換演算子.ビット演算子.型 ...

  8. Windows PowerShell 入門(1)-基本操作編

    Microsoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.インストール.起動終了方法.コマンドレット.命名規則.エイリアス.操作方法の調べ方について ...

  9. Windows PowerShell 入門(5)-制御構文

    Windows PowerShellにおける制御構文について学びます.数ある制御構文の中でもSwitch文は.他の言語に比べ豊富な機能が用意されています. 対象読者 Windows PowerShel ...

随机推荐

  1. Scoring and Modeling—— Underwriting and Loan Approval Process

    https://www.fdic.gov/regulations/examinations/credit_card/ch8.html Types of Scoring FICO Scores    V ...

  2. JAVA核心技术I---JAVA基础知识(列表List)

    一:List了解 (一)List:列表 –有序的Collection –允许重复元素 –{,,,{,},,} (二)List:主要实现 同步/非同步:针对线程而言 –ArrayList(非同步的) – ...

  3. 原生JavaScript运动功能系列(三):多物体多值运动

    多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素 ...

  4. 在ServiceModel客户端配置部分中,找不到引用协定“”的默认终结点元素

    鄙人自己写了一个读取文件的ASP.NET服务,在Silverlight工程中添加服务引用(名字为FileIOService)后,出现了如上的错误. 出错原因:服务是在项目B中调用的,但是主项目是A,所 ...

  5. mysql load_file在数据库注入中使用

    load_file函数只有满足两个条件就可以使用: 1.文件权限:chmod a+x pathtofile 2.文件大小: 必须小于max_allowed_packet 例子: select load ...

  6. 树链剖分模板(洛谷P3384)

    洛谷P3384 #include <bits/stdc++.h> #define DBG(x) cerr << #x << " = " < ...

  7. Centos7下安装小米SQL优化工具SOAR

    1 下载源码包 赋予权限 wget https://github.com/XiaoMi/soar/releases/download/0.9.0/soar.linux-amd64 -O soar ch ...

  8. 4-23 模块 hashlib ,configparser,loging,collections

    1,hashlib模块的补充(摘要算法) 1,Sha1的用法和md5的类似,通常用一个40位的16进制字符串表示.比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度 ...

  9. Visual Studio 2013 在使用 razor无智能提示的解决办法

    网上看到的方法都差不多,但是我感觉没怎么说详细,因此,截图备注下: 1.开始->Microsoft Visual Studio 2013->Visual Studio  Tools-> ...

  10. git操作手册

    git教案链接:https://git-scm.com/book/zh/v2 1.1 起步 - 关于版本控制 于是分布式版本控制系统(Distributed Version Control Syste ...