Windows PowerShell: 短縮構文
多くの場合、Windows PowerShell では、1 つのタスクを実行する手法が複数あります。あなたにとって最適な方法を見つけて、手間と時間を省きましょう。
Don Jones
Windows PowerShell の柔軟性は、長所にも短所にもなる特性の 1 つです。多くの点で、Windows PowerShell は、プログラミング言語のように記述できます。プログラマでなければ、この点は無視して、コマンド ライン シェルのように使用しても問題ありません。
ただし、完全に "無視" するのは得策ではないかもしれません。ご存じのように、通常、Windows PowerShell では、1 つのタスクを実行する方法が 3 ~ 4 とおりあります。しかし、最もわかりやすい方法を 1 つ知っていれば十分です。ただし、賢明な Windows PowerShell ユーザーは、目的のタスクを遂行する方法すべてに精通しています。すべての方法に精通していれば、他のユーザーが記述したコードを読んだときに、そのコードの目的を把握できます。
エイリアスについて
エイリアスは、ユーザーが最初に覚える "ショートカット" (短縮形) です。次のコマンドについて考えてみましょう。
PS C:\> Get-WmiObject -class Win32_LogicalDisk -Filter "DriveType=3" | >> Where-Object -FilterScript{ $_.FreeSpace / $_.Size -lt .1 } | >> Select-Object -Property DeviceID,FreeSpace,Size >>
このコマンドは次のように短縮できます。
PS C:\>gwmi Win32_LogicalDisk -Fi "DriveType=3" | >> ?{ $_.FreeSpace / $_.Size -lt .1 } | >> SelectDeviceID,FreeSpace,Size >>
ここでは、コマンド名の代わりにエイリアスを使用して、パラメーターの文字数を減らしました。個々のパラメーター名を識別するのに十分な長さがあることが条件になりますが、Windows PowerShell では、パラメーター名を短縮できます。この性質を利用すると入力する文字数は少なくなりますが、コマンドが大幅に解読しづらくなります。そのため、私は、サンプルを掲載するとき、スクリプトに保存するとき、またはその他の成果物とするときには、コマンドを省略せずにスペルアウトするように指導しています。このようにすると、後で見たときに、わかりやすくなります。
Windows PowerShell ISE や他のほとんどのエディターでは、パラメーター名の一部を入力して Tab キーを押すと、残りの文字列が自動的に入力されます。入力する文字数が少なくなり、読みやすさが向上します。その他のパラメーター名は位置を特定するためだけのものなので、すべて省略しました。つまり、正しい順序でパラメーターを指定している限り、コマンドは問題なく機能します。
ただし、途中で省略された名前は読みにくいものです。スクリプトでは、パラメーター名を省略しないことが、多くの人に喜ばれるでしょう。また、パラメーターの順序を覚えておく必要がなくなるので、最終的には、皆さんの手間も省けます。正式な名前を使用するときは、好きな順序でパラメーターを配置できます。
引用符で囲まれた式
ときとして、引用符で囲まれた文字列に式の結果を挿入しなければならないことがあります。このようにすることで、式の結果をスクリプトの出力に含めることができます。これを実行する手段の 1 つとして、結果を変数に格納する方法があります。その後、変数を二重引用符で囲まれた文字列に挿入する Windows PowerShell の手法を使用します。この手法を使用すると、Windows PowerShell では、変数をその内容で置き換えます。
$disk = Get-WmiObject -class Win32_LogicalDisk -filter "DeviceID='C:'" $freepercent = $disk.freespace / $disk.size * 100 Write-Host "Free space on drive C: at $freepercent percent"
また、Windows PowerShell では二重引用符の中に完全な式を挿入することもできます。この構文は Unix シェルの手法から派生しています。若干奇妙に見えるかもしれませんが、多くのユーザーが使用しています。
$disk = Get-WmiObject -class Win32_LogicalDisk -filter "DeviceID='C:'" Write-Host "Free space on drive C: at $($disk.freespace / $disk.size * 100) percent"
私が最初の形式を好むのは、Windows PowerShell の初心者と関わることが多いためです。最初の形式の方が多少解読しやすいでしょう。スクリプトの各行で 1 つの処理が実行されるため、ロジックが少し理解しやすくなります。
Windows PowerShell では、記号が多く使用されるため、2 つ目の形式は、わかりにくい印象を与えます。ただし、2 つ目の形式の方が、技術的に多少効率的です。2 つ目の形式では Windows PowerShell で追跡しなければならない変数を作成していません。さらに、ほとんどのユーザーが気に入る点だと思いますが、ほんの少しですが入力する文字数が減ります。
オブジェクトの作成
次のようなカスタム オブジェクトを作成するときには、長い形式の構文が便利です。
$cs = Get-WmiObject -class Win32_ComputerSystem $os = Get-WmiObject -class Win32_OperatingSystem $obj = New-Object -TypeNamePSObject $obj | Add-Member -MemberTypeNoteProperty -Name OSVersion -Value $os.version $obj | Add-Member -MemberTypeNoteProperty -Name Mfgr -Value $cs.manufacturer $obj | Add-Member -MemberTypeNoteProperty -Name Model -Value $cs.model Write-Output $obj
私は、次のように Add-Member コマンドレットを 1 つのパイプラインに組み込む手法を使用して、上記のスクリプトを少し短縮することがあります。
$cs = Get-WmiObject -class Win32_ComputerSystem $os = Get-WmiObject -class Win32_OperatingSystem $obj = New-Object -TypeNamePSObject $obj | Add-Member -MemberTypeNoteProperty -Name OSVersion -Value $os.version –PassThru | Add-Member -MemberTypeNoteProperty -Name Mfgr -Value $cs.manufacturer –PassThru | Add-Member -MemberTypeNoteProperty -Name Model -Value $cs.model –PassThru
最近は、少し異なる手法を使い始めました。こちらの方がさらに読みやすくなります。
$cs = Get-WmiObject -class Win32_ComputerSystem $os = Get-WmiObject -class Win32_OperatingSystem $props = @{'OSVersion'= $os.version; 'Mfgr'=$cs.manufacturer; 'Model'=$cs.model} $obj = New-Object -TypeNamePSObject -Property $props Write-Output $obj
繰り返しになりますが、私が、このような長い形式の構文を好む理由は読みやすさです。私は Windows PowerShell の初心者と関わることが多く、コードの内容を理解してもらううえで読みやすさはきわめて重要だからです。また、次の手法もよく使用されています。
$obj = Select-Object OSVersion,Mfgr,Model $obj.OSVersion = $os.version $obj.Mfgr = $cs.manufacturer $obj.Model = $cs.model $obj
結果は基本的に同じです。最後の手法は、入力する文字数が少しばかり少なくなります。これは Select-Object コマンドレットを使用するために、いわゆるハッカーが使用する手法です。ここでは、存在しないプロパティを選択するように指定できるという Select-Object コマンドレットの特性を利用しています。コマンドレットでは、実際にプロパティを作成しますが、出力オブジェクトの値は空になります。
このように Select-Object コマンドレットを使用することは、実際のところお勧めすべきではない (正確には、誤用) ですが、私だけがこのような方法で使用しているわけではありません。2008 年のことですが、私の仲間である Windows PowerShell MVP のメンバーが、この方法に異論を唱えていました。この手法の賛否はさておき、この手法について知っていれば、この手法を使用したコードの目的もわかります。
Windows PowerShell 3.0 では、次のコマンドを実行できるようになります。
[pscustomobject]@{'OSVersion'= $os.version; 'Mfgr'=$cs.manufacturer; 'Model'=$cs.model}
この構文に対する立場はまだ決め兼ねていますが、概ね問題ないといったところです。そこそこ読みやすく、入力する文字数も多少減らすことができます。他のユーザーも使い始めるでしょうから、存在だけでも把握しておくことをお勧めします。最後の手法は処理速度が速そうです (詳細については、Jonathan Medd's Blog (Jonathan Medd のブログ、英語) をご覧ください)。
オブジェクトの短縮
もう 1 つのよく見かける短縮手法は、文字列内の式に似ています。これは至って合法的なプログラミング構文ですが、初心者にとっては少しわかりにくいかもしれません。ただ、まったく問題はないので、ある程度慣れ親しんで、その用途を知っておくと良いでしょう。
たとえば、次のように、あるオブジェクトでメソッドを実行し、その結果として得られるオブジェクトのプロパティの 1 つを使用して、さらに処理を実行するとします。
$string = ' Hello ' $string = $string.Trim() $string.Length
かっこを使用すると、すべての処理を短縮できます。かっこで囲まれた式は最初に評価され、Windows PowerShell では、基本的に、かっこ付きの項目をその結果で置き換えます。
$string = ' Hello ' ($string.Trim()).length
記号の数が増えるので式の各項目を分けて、行われている処理を細かく把握するのは少し困難になりますが、まったく問題はありません。Windows PowerShell で変数を操作する回数が少なくなるので、実行速度もわずかながら向上する可能性があります。
謝意を表して
ある意味では、Windows PowerShell で処理の実行方法が統一されなかったのは残念なことです。もし 1 つなら、その方法を覚えれば済むわけですから。ところが実際は、本質的に同じタスクを実行するために、さまざまな構文が用意されています。そのため、代替構文を数多く知っておくことは有益です。そうすれば、さまざまな例を活用することができます。
Don Jones は、Microsoft MVP の受賞者で、『Learn Windows PowerShell in a Month of Lunches』(Manning Publications、2011 年) の著者でもあります。この書籍は、管理者が Windows PowerShell を効率的に使用できるようにすることを目的としています。また、一般ユーザーを対象にオンサイトの Windows PowerShell トレーニングも開催しています。Don に対するお問い合わせについては、ConcentratedTech.com (英語) または bit.ly/AskDon (英語) を参照してください。