PowerShell Scripting Weblog

MSMVP for PowerShellのライター牟田口大介が、Windows上で動作するスクリプティング環境(Windows PowerShell、IronPython、Windows Script Host(WSH)、HTML Application(HTA)、Windows サイドバー/デスクトップ ガジェットetc)に関するTips、コード、ニュースなどを紹介します。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  211  : 記事  1  : コメント  473  : トラックバック  46

ニュース

2010/7/1 MSMVP for PowerShell再受賞!
2010/03/23
サイト名をScripting WeblogからPowerShell Scripting Weblogに変更
2009/10/17 このブログのミラーを作りました

自己紹介

ライター兼プログラマでMSMVP for Data Center Management - PowerShell のむたぐち(牟田口大介)です。

MVP Logo

Microsoft MVP for Visual Developer - Scripting July 2004-June 2007
Microsoft MVP for Data Center Management - PowerShell July 2007-June 2011

広告

書庫

日記カテゴリ

My Sites

コミュニティ

2010年8月11日 #

正規表現は便利なのですが、「ある文字列が存在したときはマッチしない」という正規表現を書くのはちょっと考えないとできないと思います。今回考えてみたので使ってみてください。

^(?!.*【文字列】)

PowerShellによる使用例。「test」という文字列が含まれているとFalseになる。

PS C:\Users\daisuke> "test" -match "^(?!.*test)"
False
PS C:\Users\daisuke> "testAAA" -match "^(?!.*test)"
False
PS C:\Users\daisuke> "AAAtest" -match "^(?!.*test)"
False
PS C:\Users\daisuke> "AAAtestAAA" -match "^(?!.*test)"
False
PS C:\Users\daisuke> "AAAtestAAAtestAAA" -match "^(?!.*test)"
False
PS C:\Users\daisuke> "AAA" -match "^(?!.*test)"
True
PS C:\Users\daisuke> "" -match "^(?!.*test)"
True

このようにちゃんと動きます。

この正規表現の意味は、「文頭があるとマッチする。ただし、あとに0文字以上の何かの文字およびtestという文字列が続く場合はマッチしない」となります。評価対象になる文字列には必ず文頭が存在するので^が基本的にはすべてマッチするのですが、後に否定の先読み(?!・・・)をつけてマッチする条件を絞っているのがポイントです。

なお、【文字列】の部分は、任意の正規表現も使用可能です。正規表現の否定、論理反転ができるわけですね。

正規表現の否定の先読み(?!・・・)は処理系によっては使えないそうです。.NET、VBScript、JavaScript、Perl、PHPなんかの最近のバージョンでは大丈夫みたいです。

なんでもかんでも正規表現にしなくても、コードを書いてやれば大抵のことは解決します。この例でも、"test"のマッチ結果を論理否定すれば求める結果は得られます。ですが正規表現でしかプログラムの機能を拡張できないケースというのもよくありますよね。TwitterクライアントのNG処理とか。そういうときに使えばいいんじゃないかなと思います。

posted @ 0:05 | Feedback (0)

2010年7月2日 #

このたびMicrosoft MVP for Data Center Management- PowerShellのアワードを再受賞しました。表彰期間は2011年の6月までです。

マイクロソフト MVP アワードプログラムより

MVP アワードプログラムは、マイクロソフトの製品やテクノロジーに関する豊富な知識と経験を持ち、オンラインまたはオフラインのコミュニティや、メディアなどを通して、その優れた能力を幅広いユーザーと共有している個人を表彰するものです。

私はこれでMSMVP7回目の受賞となります。これも皆様の温かいご支援の賜物です。今後ともよろしくお願いいたします。

posted @ 0:18 | Feedback (7)

2010年6月25日 #

今月のWindows UpdateでVista/XP/Server 2003/Server 2008用のWindows PowerShell 2.0が提供開始になりました。Windows Server 2008の場合では次のような表示になります。

Windows Server 2008 用の Windows PowerShell 2.0 および WinRM 2.0 (KB968930)

ダウンロード サイズ: 32.4 MB

この更新プログラムを有効にするには、コンピューターを再起動する必要があります。

更新プログラムの種類: オプション

Windows 管理フレームワーク コア パッケージには、Windows PowerShell 2.0 および Windows リモート管理 (WinRM) 2.0 が含まれています。Windows 管理フレームワークの詳細については、http://support.microsoft.com/kb/968929 を参照してください。

詳細情報:
http://go.microsoft.com/fwlink/?LinkID=165613

 

公式ブログの記事:Windows PowerShell 2.0 on Windows Update - Windows PowerShell Blog - Site Home - MSDN Blogs

このアップデートは強制ではなくオプションです。このアップデートを適用すると、Windows 管理フレームワーク (Windows PowerShell 2. 0、WinRM 2. 0、および BITS 4. 0) をインストーラーを使用して適用するのと同様にPowerShell 2.0を導入することができます。なお、このインストーラーではPowerShell 1.0があらかじめシステムにインストールされている場合は前もってアンインストールする必要がありましたが、Windows Updateの場合はアンインストールの必要はなく、自動的に1.0が上書きされ2.0になります。なお.NET Framework 2.0 sp1以上がインストールされていない場合、または、正式版でないPowerShellがシステムにインストールされている場合、このアップデートは候補に現れません。

このアップデートはアンインストールすることができます。その場合はコントロールパネルの「プログラムと機能」などで「更新プログラム」を表示し、「Windows Management Framework Core」を選択します。なおこのアップデートをする前にv1.0をインストールしていた場合は、当該アップデートをアンインストールすることでPowerShellのバージョンがv2.0からv1.0に戻ります。

posted @ 22:39 | Feedback (0)

2010年5月20日 #

PowerShell的システム管理入門
第3回 ファイル/レジストリの操作

http://www.atmarkit.co.jp/fwin2k/operation/pshsys03/pshsys03_01.html

よろしくお願いしますー。

ファイル、フォルダ操作、テキストファイル読み書き、レジストリ操作などの話題です。PSプロバイダという仕組みに基づいていろいろなリソースを同じコマンドレットで扱えるところがポイントですね。

そして5/29のわんくま大阪勉強会でPowerShellのコマンドレットとPSプロバイダを開発する話をやります。ファイル、レジストリ、Active Directory、そしてTwitter…。ご興味のある方はぜひご参加ください!

posted @ 10:47 | Feedback (0)

2010年4月16日 #

PowerShellの基礎 - @IT
http://www.atmarkit.co.jp/fwin2k/operation/pshsys02/pshsys02_01.html

知っておくべき最低限の基礎文法について取り上げました。前にこのブログで書いた基礎文法最速マスターからさらにエッセンスを取り出した感じです。次回からはシステム管理法の各論に入ります。よろしくです。

ところでこのブログのタイトルをScripting WeblogからPowerShell Scripting Weblogに改名しました。よろしくです。

posted @ 0:21 | Feedback (6)

2010年3月11日 #

PowerShell的システム管理入門
―― PowerShell 2.0で始める、これからのWindowsシステム管理術 ――

@ITでPowerShellを使ったシステム管理入門の連載を始めました。どうぞよろしくお願いします。

月1更新の全10回を予定しています。予定はこちら。

第1回:PowerShellの概要―今回。概要の解説
第2回:PowerShellの基礎―PowerShellの基礎解説
第3回:ファイル/レジストリの操作
第4回:サービス/プロセスの操作
第5回:イベント・ログの操作
第6回:システム情報(WMI)の取得
第7回:ActiveDirectoryの操作
第8回:IISの管理
第9回:Hyper-Vの管理
第10回:Exchange 2007の管理

これまでWebにあるPowerShell記事は商用記事、個人ブログ問わず、どちらかというと言語的アプローチが多かったと思うのですが、今回の連載はPowerShell言語にフォーカスするのではなく、システム管理シェルとしての機能にフォーカスしています。PowerShellの開発者がシステム管理者に使ってほしいと思っているであろうシステム管理機能を勝手にランキングし、上位を取り出して目次にしました。PowerShell 2.0の段階ではたぶんこのあたりが美味しいと思っています。どうでしょう。ほかにもバックアップとか、フェイルオーバークラスタリングとか、グループポリシーとか、サーバー製品群でもSQL Server 2008とかもありますが、まずはこの辺からかなぁと。

この間、PowerShell2.0の新機能についても記事書いたのであわせてどうぞ。

それと直前の告知になってすみませんですが、今週の土曜日、名古屋でPowerShell 2.0のセッションやります。お時間の都合がつくかたでご興味があればこちらもぜひどうぞ。

posted @ 19:15 | Feedback (1)

2010年3月6日 #

ホワイトボードプログラミング
反転...ですかー
ループなしで、配列の順序を逆にする

よし、おれにまかせろ!

PS C:\Users\daisuke> $array=@(1,3,5,7,9,11)
PS C:\Users\daisuke> $array=$array[($array.length-1)..0]
PS C:\Users\daisuke> $array
11
9
7
5
3
1
posted @ 10:03 | Feedback (2)

2010年3月4日 #

PowerShell 2.0ではscriptblockにGetNewClosure()メソッドが追加され、クロージャを記述することができるようになりました。

クロージャを作るには、まず関数の中に変数(レキシカル変数)と関数(PowerShellではスクリプトブロック)を定義します。外側の関数内に定義された変数(レキシカル変数)を関数内に定義された内側の関数から操作するようにしておきます。そして外側の関数は内側の関数そのものを返却するようにしておきます。これでクロージャができました。

クロージャを使用するには、まず外部から外側の関数の戻り値(これは内側の関数です)を変数に代入します。そしてこの変数に含まれる関数(内側の関数)を実行すると、レキシカル変数に何らかの変化を及ぼしつつ結果が返却されます。ポイントは、レキシカル変数の値が保持されることです。その結果、内側の関数を実行するたびにその時のレキシカル変数の値に基づいた結果を返却するようにできるわけです。

とまあ書いても何のことかよくわからないかと思いますので実例を示します。よくある例題なのですが、「呼び出すたびに1が加算された結果を返す関数。すなわち、呼び出すと結果が、1,2,3,4…と続いていく関数」を考えます。

function counter()
{
	$x=0
	return {$script:x++;return $x}.GetNewClosure()
}

これがクロージャの本体です。ポイントは、scriptスコープを使用することで内側のスクリプトブロックからレキシカル変数(ここでは$x)の値を変更している点です。

使用法は次のようになります。変数$fにcounter関数の内側のスクリプトブロックを代入し、&演算子で実行しています。

PS C:\Users\daisuke> $f=counter
PS C:\Users\daisuke> &$f
1
PS C:\Users\daisuke> &$f
2
PS C:\Users\daisuke> &$f
3
PS C:\Users\daisuke> &$f
4
PS C:\Users\daisuke>

見事、お題を実現することができました。

さて、GetNewClosure()メソッドが追加されたことで、関数のカリー化も可能になります。カリー化とは、たとえばf(x,y)という関数があった場合、g(x)(y)という、f(x,y)と常に同じ値を返却する関数を作ることです。一般には、複数の引数をとる関数fを、fの最初の引数だけを引数にとり、「fの残りの引数をとり結果を返す関数」が戻り値であるgという関数に変換することです。これまた何のことかわかりにくいですね。

たとえば一番簡単な例。引数同士を加算する関数sumをカリー化してcurried_sumという関数を作ってみます。

function sum([int]$x,[int]$y)
{
	return [int]($x+$y)
}

function curried_sum([int]$x)
{
	return {param([int]$y);return sum $x $y}.GetNewClosure()
}

これでsumのカリー化ができました。実行してみます。

PS C:\Users\daisuke> &$(curried_sum 3) 4
7
PS C:\Users\daisuke> &$(curried_sum -6) 14
8
PS C:\Users\daisuke> &$(curried_sum -2) -3
-5
PS C:\Users\daisuke> $sum5 = curried_sum 5
PS C:\Users\daisuke> &$sum5 11
16
PS C:\Users\daisuke> &$sum5 -4
1
PS C:\Users\daisuke> $sum2 = curried_sum 2
PS C:\Users\daisuke> &$sum2 8
10
PS C:\Users\daisuke> &$sum2 1
3

PowerShellの関数の呼び出し方がわりと特殊であるため、少々分かりにくいですがサブ式$()と呼び出し演算子&をつかってカリー化されたsum関数を実行して目的通りの結果を得ています。たとえば最初の例は3+4を実行していることになり、結果はsum 3 4と同じ7になります。以下同様です。$sum5は、「引数に5を加える関数」になります。

いかがでしたでしょうか。PowerShellでも(なんか文法とか奇妙ですが)クロージャやカリー化ができて楽しいですね。というか私は本記事を書くにあたってクロージャとカリー化がなんぞやということを勉強しました…。

posted @ 12:05 | Feedback (2)

2010年2月22日 #

PowerShell 2.0では標準コマンドレットの数が1.0の129個から236個へと、107個増えています。また、既存のコマンドレットの一部にパラメータが増えています。そこで、2.0で新しく加わったコマンドレットと、新しく追加されたパラメータを列挙するスクリプトを作ってみました。

まず、1.0がインストールされている環境で、コマンドレットのリストをXMLに書き出します。次のコマンドを実行してください。

 get-command -type cmdlet|export-clixml cmdlets1.xml -depth 3

同様に、2.0の環境でも実行してください。

 get-command -type cmdlet|export-clixml cmdlets2.xml -depth 3

出来上がった二つのxmlファイルをカレントディレクトリに置いて、次のスクリプトを実行すると、新しく追加されたコマンドレットとパラメータが列挙されます。(必要なら適宜リダイレクトするなどしてファイルに落とし込んでください)

function Get-CmdletHash
{
    param([string]$path)
    $cmdlets = Import-Clixml $path
    $cmdletsHash = @{}
    $cmdlets|
        %{
            $parameters = @()
            $_.ParameterSets|
                %{
                    $_.Parameters|
                        %{
                            $parameters += $_.Name
                        }
                }
            $parameters = $parameters|Sort-Object|Get-Unique|?{"WarningAction","WarningVariable" -notcontains $_}
            $cmdletsHash.Add($_.Name,$parameters)
        }
    return $cmdletsHash
}

$ver1 = Get-CmdletHash cmdlets1.xml
$ver2 = Get-CmdletHash cmdlets2.xml

$ver2.Keys|
    %{
        if($ver1.ContainsKey($_))
        {
            $result = Compare-Object $ver1[$_] $ver2[$_]
            if($result)
            {
                "[Update] $_"  
                $result | Format-Table
            }
        }
        else
        {
            "[New] $_  `r`n" 
        }
    }

出力結果を置いておきます。こちら

このスクリプトではGet-CommandコマンドレットがSystem.Management.Automation.CmdletInfoというコマンドレットの情報を格納したオブジェクトを返すことを利用し、Export-Clixmlコマンドレットでシリアライズ化してXMLファイルに落とし込むことにより異なるバージョンのPowerShell同士を比較しています。ここで-depthパラメータを3にしているのは、パラメータ情報を格納するParametersプロパティがルートから3階層下にあるためです。(デフォルトは2階層下までを出力。PS2.0ではCmdletInfoにParametersプロパティというのがあって2階層でたどれるのですが1.0にこのプロパティはないのでParameterSetsプロパティからたどる必要があります)

また、WarningActionとWarningVariableという共通パラメータが増えているので、これらはすべてのコマンドレットに共通して追加されているパラメータなので除外しておきます。

あとはパラメータをコマンドレットごとに配列化して、Compare-Objectで比較しています。新しく追加されたコマンドレットは[New]のマークをつけ、既存のコマンドレットでパラメータに変化があるものは[Update]をつけて追加されたパラメータを列挙するようにしています。

かなりたくさんのコマンドレットでパラメータが増えたことが分かりますね。また、Get-CommandコマンドレットのPSSnapinパラメータが廃止され、Moduleパラメータに変更されたことなどが分かったりします。

1.0ユーザーだった方にお勧めのスクリプトです。

posted @ 20:58 | Feedback (0)

2010年2月13日 #

PowerShellは.NET Framework 2.0を利用するWindowsのシステム管理用シェルである。シェルであるためコンソールで対話的にコマンドを実行することができるのはもちろん、スクリプトファイル(*.ps1)を記述しバッチ的に実行することも可能である。ここではPowerShellスクリプトで(コンソールでも使用は可能だが)用いることのできる基礎文法を紹介する。なお、PowerShellでは文法上、大文字小文字を区別しない。

※(★2.0)の注釈があるものはPowerShell 2.0で新たに追加された要素である。

1.基礎

表示

コンソールに文字列を表示。

"Hello world" 

コマンドレット(後述)を使用した場合。

Write-Host "Hello world" 

コマンドレット

PowerShellはコマンドレットと呼ばれる100種類以上のコマンドライン・ツール群を単独で、あるいはパイプライン(後述)で連結して使用するのが基本となる。コマンドレットは原則verb-nounという命名規則にしたがっている。パラメータをつける場合は「-パラメータ名」あるいは「-パラメータ名 パラメータ値」を指定する。

# コマンドレットの一覧表示
Get-Command 

# サービスの一覧を表示
Get-Service 

# アプリケーション イベントログの最新15個のエントリを表示
Get-EventLog -logName Application -newest 15

パイプライン

コマンドレットが値を返却する場合、.NET Frameworkのオブジェクトが含まれる配列であることが多い。このオブジェクト配列がパイプラインを渡って後続のコマンドレットに入力される。

# プロセスのリスト(System.Diagnostics.Processオブジェクトの配列)を取得し、
# Where-Objectコマンドレットでハンドル数(handlesプロパティ)の値が500より大きいものだけを取り出し
# Select-Objectコマンドレットで最初の5つのオブジェクトだけを切りだして表示
Get-Process | Where-Object {$_.handles -gt 500} | Select-Object -first 5

# C:\Windows 配下のフォルダ、ファイルの一覧(System.IO.DirectoryInfo,System.IO.FileInfoオブジェクトの配列)を取得し、
# ForEach-Objectコマンドレットで配列を列挙しすべてのオブジェクトのFullNameプロパティ(フルパス)の値を表示
Get-ChildItem C:\Windows | ForEach-Object {$_.FullName} 

# 通常の配列に関してもパイプラインを使用可能。
# 重複を取り除き、ソートをかける
@(3,5,10,1,2,1,1,1,2,6,4,4)|Sort-Object|Get-Unique 

コメント

# コメント 

マルチラインコメント(★2.0)

<#
複数行に渡る
コメントです
#> 

変数の宣言

PowerShellは変数の宣言をしなくても変数を使用可能。以下のようにするとどのような型でも代入可能な変数が作られる。

$a = 1
$a = $b = $c = 1 #複数変数に一度に同じ値を代入する場合
$items = Get-ChildItem # コマンドレットの戻り値を格納 

変数の型を指定することは可能。以下のようにするとint型のみ格納可能な変数が作られる。

[int]$a = 1 

あるいは、コマンドレットを用いて$aという変数を宣言することもできる。この場合変数の型は指定できない。

New-Variable -name a 

変数のスコープ

# どのスコープからも読み書き可能
$global:a = 1

# 現在のスコープからのみ読み書き可能
$private:a = 1 

# 現在のスクリプトからのみ読み書き可能
$script:a = 1 

文法チェック

以下を実行することで未定義の変数を参照するとエラーが出るようになる。

Set-PSDebug -strict 

スクリプトの実行

デフォルトの実行ポリシーではスクリプトの実行は不許可であるため、以下のようにポリシーを変更しておく。(RemoteSignedはローカルにあるスクリプトファイルは無条件で実行可、リモートにあるスクリプトファイルは署名付きのもののみ実行可)

Set-ExecutionPolicy RemoteSigned 

スクリプト/コマンドを実行するにはコマンドラインで次のようにする。

コマンドを実行する

powershell -command {Get-ChildItem C:\} 

ファイルを実行する

powershell  .\script.ps1 

ドットソース(スクリプトの内容をグローバルスコープに読み込む)

powershell  . .\script.ps1 

ファイルを実行する(★2.0)

powershell -file script.ps1 

PowerShellスクリプトから別のスクリプトを実行する場合(関数のインクルードにも用いられる)

.\script.ps1
. .\script.ps1 # ドットソース 

デバッガの起動

Set-PSDebug -trace 2 

ステップ実行

Set-PSDebug -step 

2.数値

数値の表現

PowerShellにおける数値は.NET Frameworkの数値を表す構造体のインスタンスである。数値には整数、浮動小数点があり、変数に代入した段階で適切な型が設定される。

# int型(System.Int32型)
$int = 1

# System.Double型
$double = 1.001

四則演算

# 足し算
$i = 1 + 1

# 引き算
$i = 1 - 1 

# 掛け算
$i = 1 * 1 

# 割り算
$i = 1 / 1 

余りと商の求め方

# 割り算の余り
$mod = 7 % 3 

# 上記の場合の商
$div = (7 - 7 % 3) / 3 

べき乗

# 2の8乗
$i = [math]::Pow(2,8) 

インクリメントとデクリメント

# インクリメント
$i++ 

# デクリメント
$i-- 

3.文字列

PowerShellにおける文字列は.NET Frameworkの System.Stringクラスのインスタンスである。

文字列の表現

文字列はシングルクォーテーションかダブルクォーテーションで囲む。ダブルクォーテーションの中では`t(タブ)や`r`n(改行)などの特殊文字が使用でき、変数が展開される。

$str1 = 'abc'
$str2 = "def"
$str3 = "a`tbc`r`n" 

#変数展開(結果は abc def)
$str4 = "$str1 def" 

文字列操作

各種文字列操作

# 結合
$join1 = "aaa" + "bbb"
$join2 = [string]::Join(",",@("aaa","bbb","ccc") )

# 結合(★2.0)
$join2 = @("aaa","bbb","ccc") -join "," 

# 分割
$record1 = "aaa,bbb,ccc".Split(",") 

# 分割(★2.0)
$record2 = "aaa,bbb,ccc" -split "," 

# 長さ
$length = "abcdef".Length 

# 切り出し
$substr = "abcd".SubString(0,2) # ab

正規表現検索

# hitした場合はTrue,しなかった場合はFalse
$result = "abcd" -match "cd"

# 最初に見つかった文字列。添え字の1,2…には()内のサブ式にhitした文字列が格納。
$matches[0] 

正規表現置換

$result = "abc" -replace "c","d" 

4.配列

PowerShellにおける配列は.NET Frameworkの System.Arrayクラスのインスタンスである。

配列の参照と代入

# 5個の要素を持つ配列宣言と代入
$arr1 = @(1,3,5,7,9)
 
# 以下のようにも記述できる
$arr1 = 1,3,5,7,9 

# 型指定する場合
[int[]]$arr1 = @(1,3,5,7,9) 

# 1~10までの要素を持つ配列宣言と代入
$arr2 = @(1..10) 

# 1要素の配列宣言と代入
$arr3 = @(1) 
$arr3 = ,1 

# 空の配列宣言と代入
$arr4 = @() 

配列の要素の参照と代入

# 4番目の要素を参照 
$ret = $arr2[3] 

# 6~9番目の要素を含んだ配列を参照
$ret = $arr2[5..8] 

# 1~4番目と8番目の要素を含んだ配列を参照
$ret = $arr2[0..3+7] 

# 配列の末尾の要素を取り出す
$ret = $arr2[-1] 

# 5番目の要素に値を代入
$arr2[4] = 11 

# 3より小さな要素を含んだ配列を返す
$ret = $arr2 -lt 3 

配列の個数

$arr1_num = $arr1.Length 

配列の操作

$arr1 = @(1,3,5,7,9) 
$arr2 = @(1..10) 

# 配列の末尾に要素を加える(push)
$arr2 += 50 

# 配列を結合し新しい配列を作成
$arr5 = $arr1 + $arr2 

# 配列にある要素が含まれるかどうか(ここではTrue)
$arr2 -contains 2 

5.ハッシュ

PowerShellにおけるハッシュは.NET Frameworkの System.Collections.Hashtableクラスのインスタンスである。

ハッシュ変数の宣言と代入

# 3つの要素を持つハッシュの宣言と代入
$hash1 = @{a=1;b=2;c=3}
 
# 空のハッシュの宣言と代入
$hash2 = @{} 

ハッシュの要素の参照と代入

# 要素の参照
$hash1.a 
$hash1["a"] 

#要素の代入
$hash1.b = 5
$hash1["b"] = 5 

ハッシュの操作

# ハッシュに要素を追加
$hash1.d = 4 
$hash1.Add("e",5)
 
# ハッシュの要素の削除
$hash1.Remove("a") 

# ハッシュのキーの取得
$keys = $hash1.Keys 

# ハッシュの値の取得
$values = $hash1.Values 

# ハッシュの要素を列挙
foreach ($key in $hash1.Keys)
{
    $key + ":" + $hash1[$key]
} 

# キーの存在確認
$hash1.Contains("b") 

6.制御文

if文

if (条件) {

}

if ~ else文

if (条件) {

}
else{

}

if ~ elsif 文

if (条件) {

}
elseif (条件) { 

} 

while/do文

while (条件) {

}

do {

} while (条件)

for文

for ($i = 0; $i -lt 5; $i++) {

} 

foreach文

foreach ($item in $items) {

} 

switch文

case を書かないのが特徴的。またスクリプトブロックを条件文に記述できる。

switch ($i) {
    1 {"1";break}
    2 {"2";break}
    {$_ -lt 5} {"5より小さい";break}
    default {"default句";break}
}
# ここで$iに配列を指定すると配列要素すべてに対してswitch文が実行される。 

比較演算子

比較演算子の一覧。PowerShellではPerlの文字列比較演算子のような記述をおこなうが、Perlとは異なり文字列も数値も同じ書式である。

$num1 -eq $num2 # $num1は$num2と等しい
$num1 -ne $num2 # $num1は$num2は等しくない
$num1 -lt $num2 # $num1は$num2より小さい
$num1 -gt $num2 # $num1は$num2より大きい
$num1 -le $num2 # $num1は$num2以下
$num1 -ge $num2 # $num1は$num2以上 

論理演算子

# 論理否定
$ret = -not $true
$ret = !$true

# 論理積
$ret = $true -and $false 

# 論理和
$ret = $true -or $false 

# 排他的論理和
$ret = $true -xor $false 

ビット演算子

# ビット単位の否定 $ret = -bnot 0x14F4 # ビット単位の積 $ret = 0x14F4 -band 0xFF00 # 上記結果を16進数で表示する場合 $ret = (0x14F4 -band 0xFF00).ToString("X") # ビット単位の和 $ret = 0x14F4 -bor 0xFF00 # ビット単位の排他的論理和 $ret = 0x14F4 -bxor 0xFF00

7.サブルーチン

PowerShellのサブルーチンには関数とフィルタがある。関数とフィルタは呼び出し行の前で宣言する必要がある。 filter構文もfunction構文と並んで独自関数を記述するものだが、filter構文はパイプラインに渡されたオブジェクトをフィルタするのに用いる。 functionとの違いは、パイプラインに渡した配列を一度に処理するか(function)個別に処理するか(filter)

# 関数宣言の基本
function Get-Test {
    return "test"
}
# 注:returnを付けなくても関数内で出力された値はすべて呼び出し元に返却される。返却したくない場合は出力値をを[void]にキャストするか|Out-Nullに渡す。

# 引数を指定する場合
function Get-Test {
    param($param1,$param2)
    return $param1 + $param2
}
 
# 引数を指定する場合の簡易的な記述法
function Get-Test($param1,$param2) {
    return $param1 + $param2
} 

# 引数の型を指定する場合
function Get-Test {
    param([string]$param1,[string]$param2)
    return $param1 + $param2
} 

# 関数の呼び出し方(,区切りではなくスペース区切りであることに注意)
Get-Test "引数1" "引数2"

# 引数の順序はパラメータ名(引数名)を指定すると自由に指定可能
Get-Test -param2 "引数2" -param1 "引数1" 

# フィルタ宣言の基本
filter Get-Odd {
    if($_ % 2 -eq 1){
        return $_ 
    }else{
        return
    }
} 

# フィルタの使用
@(1..10) | Get-Odd

8.テキストファイル入出力

コマンドレットで可能。エンコーディングは日本語環境のデフォルトではShift-JIS。コマンドレット出力のテキストファイルへの書き出しに関してはリダイレクトも可能。この場合エンコーディングはUnicode。

$str1 = "testテスト"
Set-Content test.txt $str1 # 書き込み
Add-Content test.txt "追記" # 追記
$str2 = Get-Content test.txt # 読み込み

Set-Content test.txt $str1 -encoding UTF8 # UTF-8で書き込み

# リダイレクト
Get-Process > test.txt # 書き込み
Get-Process >> test.txt # 追記
Get-Process | Out-File test.txt -encoding UTF8 # エンコーディングを指定する場合

9.例外

PowerShellで例外が発生すると、デフォルトではエラーメッセージを表示し次の行を実行する(シェル変数$ErrorActionPreferenceの設定により挙動の変更可能)。VBでいうとOn Error Resume Nextに近い。エラーが発生すると$Errorにエラー情報の配列が格納され、$?にFalseが格納される。エラーをトラップするには次の構文を使用する。VBでいうとOn Error Goto lineに近い。

# すべてのエラーをトラップ
trap {

}

# エラーの型名を指定してトラップ
trap [System.Management.Automation.CommandNotFoundException] {

} 

# エラーを発生させる
throw "エラー"
throw New-Object NullReferenceException 

構造化例外処理(★2.0)

# 基本
try{

}
catch{

}
finally{

} 

# エラーの型を指定してcatch
try{

}
catch [System.Net.WebException],[System.IO.IOException]{

}

10.知っておいたほうがよい文法

行継続文字

1行にすると長いコードを複数行に書くには行継続文字`を用いる。VBの_。

$items = Get-ChildItem a*,b*,c*,d*,e* `
-force -recurce 

ただし以下のような場合は`を使用しなくてもよい

$items =
    Get-ChildItem a*,b*,c*,d*,e* -force ?recurse
    
Get-Process | 
    Where-Object {$_.handles -gt 500} |
    Select-Object -first 5 

ステートメント分割

ステートメントを分割するには改行コードもしくは;を使用する。VBの:。JavaScriptと同様、文末に;はつけてもつけなくてもよい。

$i = 1; $j = 5; $k = $i + $j 

ヒア文字列

複数行の文字列を記述する方法。

$str = @"
aaaaaa
bbbbb
cccc
ddd
ee
"@ 

.NET Frameworkクラスの利用

.NET Frameworkに含まれているクラスのプロパティやメソッドを使用できる。基本的に完全修飾名を指定しなければいけないが、"System."は省略可能。また、intなど型エイリアスがいくつか定義されている。

# スタティックメンバの使用
[System.Math]::Pow(2,8) 

# インスタンスの生成とメソッドの実行
$arrayList = New-Object System.Collections.ArrayList
$arrayList.Add("a") 

# コンストラクタがある場合。複数ある場合は配列として指定
$message = New-Object System.Net.Mail.Message from@example.com,to@example.com

# COMオブジェクトの生成
$wshShell = New-Object -com WScript.Shell 

# デフォルトで読み込まれていないアセンブリを読み込む
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.MessageBox]::Show("hello!") 

# クラスにどんなメンバがあるかの確認
# インスタンスメンバ
Get-ChildItem | Get-Member 

# スタティックメンバ
[math] | Get-Member -static 

キャスト

-asを使った場合はキャスト失敗時もエラーにならずNullが格納される。

$dt = [System.DateTime]"2010/02/13"
$dt = "2010/02/13" -as [System.DateTime] 

ユーザー定義オブジェクト

PowerShellにはクラスを定義する構文はないが、空のオブジェクト(PSObject)を生成し、任意のプロパティ(ノートプロパティ)を付加することができる。

$obj = New-Object PSObject
$property = New-Object System.Management.Automation.PSNoteProperty "Name","名前"
$obj.PSObject.Members.Add($property) 

シェル変数

あらかじめ定義されている変数。シェル変数には自動変数(変更不可能)とユーザー定義変数(変更すると挙動を変更することができる)がある。自動変数の例を挙げる。

$_ :現在パイプラインにわたっているオブジェクト
$args :関数やスクリプトに与えられたパラメータの配列
$pshome :PowerShellがインストールされているフォルダのフルパス
$MyInvocation :スクリプトの実行情報。$myInvocation.ScriptNameでスクリプトのフルパス取得(★2.0)。$myInvocation.MyCommand.Path(1.0の場合)
$true :true。
$false :false。
$null :null。

サブ式

$()内には複数行のコードが記述できる。

$arr = $(1;2;1+4)

式モードとコマンドモード

PowerShellの構文解析は式モードとコマンドモードがある。式モードは通常のモード。コマンドモードは引用符がなくても文字列を文字列として扱う。コマンドレットのパラメータなどはコマンドモードで扱われる。ただしコマンドモードになるところでも()もしくは$()もしくは@()をつけるとその中身は式モードとして解釈、実行される。

$i = 1 + 1 # 式モード
Write-Host aaa # コマンドモード(表示:aaa)
Write-Host aaa bbb # コマンドモード(表示:aaa bbb)
Write-Host 1+1 # コマンドモード(表示:1+1)
Write-Host (1+1) # 式モード(表示:2)
$itemCount = @(Get-ChildItem).Length # 式モード

実行演算子とスクリプトブロック

&演算子を用いるとスクリプトブロック{}の内容を実行できる。この場合、スクリプトブロック内のコードは別スコープになる。

$script = {$i = 1+6; Write-Host $i}
&$script
& 'C:\Program Files\Internet Explorer\iexplore.exe' # パスにスペースの含まれるファイルを実行したりするのにも使える

 

フォーマット演算子

-f演算子を使うと、.NET Frameworkのカスタム書式が使用可能。

"{0:#,##0}Bytes" -f 38731362 # 表示:38,731,362Bytes

バイト数の簡易表記

$i = 1KB # 1024が代入される
$i = 1MB # 1048576が代入される
$i = 1GB # 1073741824が代入される

そのほかの基礎文法最速マスターへのリンク

プログラミング基礎文法最速マスターまとめ - ネットサービス研究室
http://d.hatena.ne.jp/seikenn/20100203/programmingMaster

PowerShellの詳しい機能解説についてはこちらの記事を参照してください。
PowerShell的システム管理入門 ―― PowerShell 2.0で始める、これからのWindowsシステム管理術 ―― ─ @IT
進化したPowerShell 2.0 ─ @IT

文法や機能について詳しく学びたい方には書籍もあります
Windows PowerShellポケットリファレンス
PowerShellによるWindowsサーバ管理術

posted @ 7:12 | Feedback (5)