連載
» 2009年07月29日 00時00分 UPDATE

基礎解説 演習方式で身につけるチェック式WSH超入門:第19回 TextStreamオブジェクトとDictionaryオブジェクトを使う [最終回] (2/2)

[牟田口大介(Microsoft MVP Data Center Management - PowerShell),著]
前のページへ 1|2       

 FileSystemObjectが含まれるMicrosoft Scripting Runtimeライブラリには、今回取り上げたTextStreamオブジェクトなど、いくつかのオブジェクトが存在する。これまでのオブジェクトはすべてFileSystemObjectオブジェクトをCreateObjectして、そこからたどり着くことができたが、1つだけたどり着けないオブジェクトが存在する。それがDictionaryオブジェクトである。DictionaryオブジェクトはProgIDが“Scripting.Dictionary”であり、これだけは直接CreateObjectして作成する。

 さて、Dictionaryオブジェクトであるが、これはほかのプログラミング言語やスクリプト言語でいうところの連想配列(ハッシュ)と同等のものである。連想配列とは、(重複しない)一意なキーと、それに対応する値を持つ、配列の一種である。キーや値には任意のデータ型を用いることができる。連想配列はキーを検索するのが速いという特長がある。ただし、キーの格納順序については保証されない。例えば要素を列挙した際、最後に追加した要素が最後に現れるかどうかは分からない。

 最も簡単な連想配列を作成し、キーと値を読み書きする例をお見せしよう。

※ファイル:DictionaryTest.vbs

Option Explicit
Dim objDictionary
'連想配列の作成
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")
'キーと値の追加
objDictionary.Add "kona","Konata Izumi"
objDictionary.Add "kaga","Kagami Hiiragi"
objDictionary.Add "tuka","Tsukasa Hiiragi"
objDictionary.Add "yuki","Miyuki Takara"

'値の参照
MsgBox "キー「kaga」の値は、「" & objDictionary("kaga") & "」です。"

'キーの存在確認
If objDictionary.Exists("yuki") Then
MsgBox "キー「yuki」は、存在します。"
End If

'要素の数を表示
MsgBox "Dictinaryに含まれる要素数:" & objDictionary.Count

Dim strKey, strMessage
'辞書の列挙
For Each strKey In objDictionary.Keys
        strMessage = strMessage & objDictionary(strKey) & vbCrLf
Next
MsgBox strMessage
objDictionary.RemoveAll() '辞書の全要素削除
objDictionary = Nothing

このスクリプトを実行すると、次のようなダイアログが連続して表示される。

1.キーの値の表示
wi-scr04.gif
2.キーの存在の確認
wi-scr05.gif
3.Dictionaryに含まれる要素数
wi-scr07.gif
4.キーに含まれる値の列挙
wi-scr06.gif DictionaryTest.vbsの実行結果

 このスクリプトでは、まず連想配列(Dictionaryオブジェクト)を作成している。次にAddメソッドを使って文字列型のキーと値を追加している。ここでは「kona」などがキー、「Konata Izumi」などが値である。あるキーに含まれる値を参照するには、Itemプロパティ(既定プロパティなので省略可)でキーを引数に与えることで可能である。すなわち、objDictionary("kaga")のようにする。キーが存在するかどうかはExistsメソッドを用いて調べる。存在するとTrue、存在しなければFalseを返す。要素の数はCountプロパティで取得できる。ところで、連想配列はすでに存在するキーを追加しようとするとエラーになるので、キーが重複する可能性がある場合は、

If Not objDictionary.Exists("misa") Then
        objDictionary.Add "misa","Misao Kusakabe"
End If

のようにキーの存在を確認して、ない場合は追加する(逆に存在する場合は特別な処理をするなど)、ということをする場合がよくあるので覚えておいてもらいたい。

 キーの一覧はKeysプロパティで取得できる。これはキーの一覧が1次元配列として格納されているので、For 〜 Each 〜 Nextステートメントで列挙できる。値の一覧もItemsプロパティで取得できるので覚えておくとよいだろう。これらのキーに対応する値を取得して、最終的にまとめて表示している。最後にRemoveAllメソッドを呼び出し、連想配列を空にしている。なお、Removeメソッドを用いると、特定のキーのみ削除することも可能である。

 連想配列が一意のキーのみを持ち自由に追加、削除ができるということを利用すると、可変長の配列として便利に利用することもできる。その場合、キーに実際に使用する値を指定し、キーに対する値は0や "" (長さ0の文字列)などを格納しておけばよいだろう(ただし、重複する値があり得るデータに対してはこの方法は使えない)。

 ほかにもDictionaryオブジェクトの特性を用いた便利な使い方もある。それをDictionaryオブジェクトの使い方の復習を兼ねた例題としてみよう。

 あるテキスト・ファイル(ここでは引き続きデスクトップのtest.txtを用いる)を開き、そこに含まれる文字数(出現回数)を文字ごとにカウントする例を考えてみよう。ただし2回以上出てきた文字だけを表示することにする。例えば「あ」が2回、「え」が3回、……などと表示させる。これはDictionaryオブジェクトを用いると比較的容易に行える。

CHECK!

マーカーで隠れたところを選択してチェックしてみよう。


※ファイル:CountCharacters.vbs

Option Explicit
Dim objFSO, objWshShell, objDictionary
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objWshShell = WScript.CreateObject("WScript.Shell")
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")

'デスクトップ・フォルダの取得とtest.txtのフルパスの構築
Dim strFilePath, strContent
strFilePath = objFSO.BuildPath( _
                objWshShell.SpecialFolders("Desktop"), _
                "test.txt")
'テキスト・ファイルをすべて読み出す
On Error Resume Next
strContent = objFSO.OpenTextFile(strFilePath).ReadAll()
On Error Goto 0
strContent = Replace(strContent, vbCrLf, "") '改行を取る。

Dim intCounter, strCharacter
For intCounter = 1 To Len(strContent) 'すべての文字についてループ
        strCharacter = Mid(strContent, intCounter, 1) '1文字切り出す
        If objDictionary.Exists(strCharacter) Then 'もし連想配列に存在すれば
                '値を+1する
               objDictionary(strCharacter) = objDictionary(strCharacter) + 1
        Else 'もし連想配列に存在しなければ
                'キーはその文字、値は1として連想配列に追加
               objDictionary.Add strCharacter, 1
End If
Next

Dim strMessage
'すべてのキーに対して列挙
For Each strCharacter In objDictionary.Keys
        '文字数が1より多ければ、strMessageに「文字: 回数」を追加
        If objDictionary(strCharacter) > 1 Then
                strMessage = strMessage & strCharacter & ": " & _
                objDictionary(strCharacter) & vbCrLf
        End If

Next

MsgBox strMessage

Set objFSO = Nothing
Set objWshShell = Nothing
Set objDictionary = Nothing

 このスクリプトを実行すると、例えば次のようになるだろう。

wi-scr08.gif

CountCharacters.vbsの実行例
test.txtに含まれる「文字: 回数」が表示されている。1回しか出現していない文字は表示されないので、回数はすべて2以上になっている。


 このスクリプトでは、まずstrContentという変数にtest.txtの中身をすべて読み出している。この際、TextStreamオブジェクトを変数で受けず、そのままReadAllメソッドを呼び、コード記述量を減らしているのがポイントである。

 続いて、読み出した文字列から、Mid関数とForループを用いて1文字ずつ切り出している。切り出した文字が連想配列に含まれていなければ新しく追加し、値に1を格納する。これはその文字が1文字あるという意味である。もし切り出した文字が連想配列に含まれていれば、そのキーに対応する値を+1する。これを繰り返すことで、文字ごとの出現回数がカウントできることが分かるだろう。


 今回はTextStreamオブジェクトを用いたテキスト・ファイルの読み書きと、Dictionaryオブジェクトを用いた連想配列の取り扱い方について述べた。

 さて、このWSH連載は今回が最終回である。本連載ではVBScriptの文法からWSHの基本機能まで一通り解説したが、お役に立てたであろうか。

 WSHは連載開始当初はWindows XP/Windows Server 2003版のVer.5.6が最新であったが、その後もマイナー・バージョンアップが続けられ、Windows Vista/Windows Server 2008にはVer.5.7が、Windows 7/Windows Server 2008 R2にはVer.5.8が搭載されている。Windows XPもパッチを当てることでVer. 5.7が適用される。今後Windowsのスクリプト実行環境のメインストリームはPowerShellに移行していくが、「お手軽」で、「どこででも動く」WSHはこれからもまだまだ使われるはずである。また、WSHに含まれるオブジェクト(WshShellオブジェクトなど)はPowerShellからも利用価値が高いものである。ぜひ、本連載やスクリプト・センターなどを参考にして、WSHをPCやサーバの管理に役立ててもらいたい。

 途中、休載期間をいただいたが3年にわたる長期連載となった。長い間、この連載をご愛読いただき、ありがとうございました。

「基礎解説 演習方式で身につけるチェック式WSH超入門」のインデックス

基礎解説 演習方式で身につけるチェック式WSH超入門

前のページへ 1|2       

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。