• テキストの超弦理論

Windowsのコマンドのいくつかパイプ処理を想定しておらず、平気で1件のレコードを複数行で出力する。どちらかというと人が見て分かりやすい書式で出力されている。おそらく、cmd.exeでは満足なパイプ処理が行えなかったからだろう。これに対してUnix/Linux系のコマンドは1件1行とするものが多く、人間が見やすいようにするには別途オプション指定するなど、パイプ処理を基本にしている。

Windows XPで追加されたtasklist.exeのような一部のコマンドは少しまともである。1行1件の出力を行えるし、“/FO csv”オプションを付けることでCSV形式での出力ができる。しかし、同じXPから搭載されたサービス管理コマンドsc.exeなどは1件の情報を複数行に出力する。

PowerShellには、サービス関連のコマンドが用意されているのでsc.exeを使う必要はない。問題はPowerShellがコマンドを持たない機能だ。こうした機能の1つに無線LAN関連の機能がある。無線LAN関連の機能は、いまのところnetsh.exeコマンドでしかアクセスできない。

たとえば、近隣にある無線LANのアクセスポイントの情報を得るには、以下のコマンドを使う(写真01)。


netsh.exe wlan show networks mode=bssid
  • 写真01: netshによる接続可能なアクセスポイントの検出。アクセスポイント情報の先頭行のみ“SSID”がスペースなしで始まり、複数行の情報が続く

このコマンドの出力のように1件が複数行にまたがるテキストを、1件ごとに分離してオブジェクトの中に入れるのは、結構面倒な処理だ。これを理解させるには、プログラムを書かねばならないと多くの人は思うだろう。

万能ではないが、PowerShellの“ConvertFrom-String”コマンドを使うと、プログラムを作らずにテキストを分解してオブジェクト化することが可能だ。具体的には、


netsh wlan show networks mode=bssid | ConvertFrom-String -TemplateFile .\wtmpl.txt
  • 写真02: ConvertFrom-Stringと作成したテンプレート(リスト参照)を使うことで、コードを書くことなくテキストからの情報抽出を行える。とはいっても、対象の構造が複雑だとエラーになることも

とする(写真02)。テンプレート(wtmpl.txt。リスト01)は、netshコマンドの出力を加工して作る。

■リスト01


SSID {NetNumber*:1} : {NetName:480000000000-2G}
    ネットワークの種類            : {NetType:インフラストラクチャ}
    認証          : {Auth:WPA2-パーソナル}
    暗号化              : {Crypt:CCMP}
    BSSID 1                 : {BSSId:01:02:33:45:67:91}
         シグナル             : {Signal:38}%
         無線タイプ         : {WiFiType:802.11n}
         バンド               : {Band:2.4} GHz
         チャネル            : {Channel:10}
         Bss ロード:
             接続されていステーション:         {NumberOfStation:1}
            チャンネル使用率:        {UsageRate:26} (10 %)
             空き容量: {FreeCapacity:0} (0 us/s)
         基本レート (Mbps) : {BasicRate:1 2 5.5 11}
         他のレート (Mbps) : {OtherRate:6 9 12 18 24 36 48 54}

SSID  {NetNumber*:2} :  {NetName:7C123456ABCD_2G}
    ネットワークの種類            : {NetType:インフラストラクチャ}
    認証          : {Auth:WPA2-パーソナル}
    暗号化              :  {Crypt:CCMP}
    BSSID 1                 : {BSSId:7c:00:11:23:45:ac}
         シグナル             : {Signal:88}%  
         無線タイプ         : {WiFiType:802.11n}
         バンド               : {Band:2.4} GHz
         チャネル            : {Channel:11} 
         基本レート (Mbps) : {BasicRate:1 2 5.5 11}
         他のレート (Mbps) :  {OtherRate:6 9 12 18 24 36 48 54}

これを「自動生成されたサンプル駆動型解析」と呼ぶ。テンプレートで抜き出したい部分を示せば、内部的にコードが自動生成され、これを処理する。

テンプレートでは、抜き出したいパラメーター部分を波括弧でくくって、自分で決めたプロパティ名を書き、コロン“:”で例示値と区切る。このとき、プロパティ名の後ろに“*”を付けると、そこが繰り返し構造の先頭になる(リスト01の先頭行)。以後、同じ部分があれば、そこが繰り返しの先頭になる(同17行目)。

別のプロパティで“*”を使うと入れ子構造を作ることができ、部分構造が繰り返すような場合に対応できるが、プロパティも入れ子構造になるため、コマンドでの扱いが少し面倒になる。

テンプレートには、複数の例を含める。プロパティ値となる部分に異なる記号文字が含まれているような場合などは複数パターンを登録する必要がある。最低でも2つの例を入れないと、1件の区切りを正しく認識できない。

1件の情報に対して“*”を複数使うなどして複雑なテンプレートを作ると、エラーになることが多い。エラーメッセージには「Microsoftに情報を送れ」といった文言があるので、まだ改良の余地があるのだろう。たとえば、アクセスポイントには、BSSIDを複数持つものがあるのだが、これを処理させようとすると解析を間違う、あるいはエラーを起こすことがある。

この機能は2015年のPowerShell 5.0で搭載されたが、現行のWindows PowerShell(Ver.5.1)とPowerShell(Ver.7.3.6)では、同じテンプレートでも振る舞いが少し異なるようだ。とはいえ、プログラムや正規表現を書かずに、元の情報からテンプレートを作るだけでテキストを解析できる。できれば、もう少し「頑強性」を高め、ちゃんとしたドキュメントを作ってほしい。

今回のタイトルネタは、「Super String Theory」(超弦理論)である。「String Theory」(弦理論)は、タイトルネタとして過去に一回扱ったが両者は異なるものだ。1970年に登場した「弦理論」は、粒子を振動する弦の端点とすることでいくつかの現象を説明したが、実験と矛盾したため衰退してしまった。その後、多次元の時空と微少な弦の長さを導入した「超弦理論」として復活する。ただし実験による実証が困難なため、定説には至っていない。文字列(String)が集まったテキストの処理という意味で、今回は超弦理論をネタにした。

テキスト処理は、プログラムを書くほか、正規表現を使う手法がこれまで使われてきた。正規表現ではコードを生成して実行する仕組みが使われ、高速な処理が可能だ。そして第3の方法として登場したのが「例示で処理を自動生成」する手法である。プログラムを書くよりも簡単で、正規表現に比べると理解しやすい。ただ、現状、コードや正規表現のように細かく調整することができないのが欠点。流行するかどうかは、実装次第と思われる。