このブログでは、PowerShell コマンドを使用して効率化するための3つのヒントを提供します。文字列内のテキストを検索し、MSQL データを XML と JSON の両方に変換し、XML スキーマを構築するための作業が効率よくできるようにする方法を具体的に説明します。
多くのルーチンタスクを自動化できる PowerShell は、Windows システムをサポートするシステム管理者には非常に有益です。開発者にとっては、PowerShell は他のスクリプト言語の代替物になります。ほとんどの Windows マシンに標準装備されており、PowerShell をインストールしたり特別なセットアップをしたりする必要はありません。
他のコーディング・ツールと同様、PowerShell にも、うまく対処する必要があるちょっとしたくせがあります。
ヒント#1 - PowerShell における Grep 機能である Select-String を使用する
PowerShell スクリプトを書いていて、文字列やテキストファイルの中のテキストを検索する必要が生じた場合、どうしますか?Unix/Linux の場合は、いくつかのオプションを使ってテキストを検索できる grep ユーティリティがあります。
Windows には、このユーティリティは存在しません。その代わり、Select-String コマンドレットを使うことができます。たとえば、様々なな従業員の名前と住所を含む大きな文字列があって、その構造がよく知られた一般的なものでない場合、従業員名を取り出すにはテキスト解析を行う必要があります。
どうすればいいでしょうか?まず、ここで例として使用する文字列を見てみましょう。
||Adam Bertram|| 2122 Acme Ct, Atlantic City, NJ
--||Joe Jonesy||-- 555 Lone St, Las Vegas, NV
==|Suzie Shoemaker|== 6783 Main St, Los Angelas, CA
この文字列が $employees という変数名を割り当てられていると仮定します。文字列から従業員の名前を取得するためには、Select-String の右に、シンタックスを並べます。まず、Pattern パラメータを使って従業員名の1つを静的に検索してみます。
PS> $employees | Select-String -Pattern 'Adam Bertram'
||Adam Bertram|| 2122 Acme Ct, Atlantic City, NJ
--||Joe Jonesy||-- 555 Lone St, Las Vegas, NV
==|Suzie Shoemaker|== 6783 Main St, Los Angelas, CA
Select-String は何かを返してきました。検索に失敗したら何も返さないので、何かを返したということは一致するものが見つかったことを意味します。ですが、Select-String が文字列全体を1個の最小単位として解析したため、返ってきたものは文字列全体でした。
Select-String に、一行ずつを異なる文字列として認識させなければなりませんが、各従業員のレコードはそれぞれ別の行にあるので、改行文字(`n)を使って分割できます。
PS> $employees = $employees -split "`n"
PS> $employees | Select-String -Pattern 'Adam Bertram'
||Adam Bertram|| 2122 Acme Ct, Atlantic City, NJ
検索結果として正しい一行だけが返ってきました。
次に、すべての従業員の情報を獲得できるよう指定する必要があります。それぞれの行に共通したパターンがあるかをチェックすると、各従業員の名前が縦棒(|)で囲まれているのがわかります。各従業員の名と姓はスペースで区切られているので、これも考慮に入れます。
Select-String の Pattern パラメータを使い、次のように指定すると、このパターンを正規表現として表すことができます。
PS> $employees | Select-String -Pattern '\|\w+ \w+\|'
||Adam Bertram|| 2122 Acme Ct, Atlantic City, NJ
--||Joe Jonesy||-- 555 Lone St, Las Vegas, NV
==|Suzie Shoemaker|== 6783 Main St, Los Angelas, CA
今度は、Select-String が返す内容は、正規表現になっています。
ここでは住所の情報は使用せず、それぞれの社員名を解析します。社員名の解析のために、Select-String が返すマッチしたオブジェクトの Matches プロパティを参照します。
PS> $employees | Select-String -Pattern '\|\w+ \w+\|' | foreach {$_.Matches}
Groups : {0}
Success : True
Name : 0
Captures : {0}
Index : 1
Length : 14
Value : |Adam Bertram|
Groups : {0}
Success : True
Name : 0
Captures : {0}
Index : 3
Length : 12
Value : |Joe Jonesy|
Groups : {0}
Success : True
Name : 0
Captures : {0}
Index : 2
Length : 17
Value : |Suzie Shoemaker|
上を見ると、Value プロパティには必要な従業員名が含まれていますが、パイプ文字(縦棒)に囲まれています。
これは、正規表現を使った検索でパイプ文字に囲まれたものを指定したためです。検索にはパイプ文字を含める必要がありますが、検索結果としてはパイプ文字を含まない文字列が欲しいところです。返してほしい検索結果をカッコで囲む正規表現グループを使用する方法があります。
この例では、従業員の名と姓を表す正規表現文字列をカッコで囲んで、指定します。
PS> $employees | Select-String -Pattern '\|(\w+ \w+)\|' | foreach {$_.Matches}
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 1
Length : 14
Value : |Adam Bertram|
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 3
Length : 12
Value : |Joe Jonesy|
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 2
Length : 17
Value : |Suzie Shoemaker|
Value には、まだパイプ文字が含まれていますが、Groups のプロパティが {0} ではなく、{0,1} になっています。これは、Select-String がグループを認識したことを意味します。
Groups プロパティは配列なので、グループの各要素を表示するには、foreach ループを使います。カッコで囲んだ [1] の要素について、Value プロパティを参照するようにします。
PS> $employees | Select-String -Pattern '\|(\w+ \w+)\|' | foreach {$_.Matches.Groups[1].Value}
Adam Bertram
Joe Jonesy
Suzie Shoemaker
これで文字列から各従業員の名前を取り出すことができました。
ヒント#2 – PowerShell を使って MySQL データを XML や JSON に変換
PowerShell では考えられる限りのあらゆるデータソースを扱うことができます。Windows の PowerShell は Windows の .NET Framework に依拠しており、PowerShell 言語のバージョンが特定のデータソースの操作をサポートしない場合も .NET オブジェクトを直接呼び出すことは常に可能です。この柔軟性があるので、PowerShell は、データをあるフォーマットから別のフォーマットに変換するのに最適なスクリプト言語と言えます。
PowerShell ヒントの2番目として、Windows PowerShell スクリプトを使用して、異なるデータソースからのデータを変換する2つの例を紹介します。Windows MySQL サーバー上の MySQL データベースからデータを取り出し、XML と JSON の2種類の構造化フラットファイルに変換します。どちらの場合も、Windows MySQL サーバーと、その中にデータを取得したいテーブルのあるデータベースがあると仮定しています。
また、サーバー自体から管理するのではなく、MySQL インスタンスにリモートで接続できる MySQL ワークベンチのようなクライアント・ソフトウェアからサーバーを管理していることを前提にしています。PowerShell コマンドを使用して、MSQLデータをXMLとJSONの両方に変換できます。
MySQL から XML へ
ConvertMySqlRow-ToXml.ps1 をダウンロードすると、C:\ConvertMySqlRow-ToXml.ps1 に PowerShell スクリプトを取得できます。このスクリプトには、同じ名前の関数が含まれています。
この関数を使用するには、関数をセッションにドットソース形式で読み込む必要があります。これはセッションのファイル内に関数をロードすることを意味し、他の PowerShell コマンドレットや関数と同様に使用することができます。ドットソース形式での読み込みを行うには、ドットと空白スペースに続けて PowerShell スクリプトのパスを入力します。
. C:\ConvertMySqlRow-ToXml.ps1
これで、変換を実行するために必要なすべてが整いました。Connect-MySQLServer と Invoke-MySqlQuery 関数を使用して、SynergyLogistics データベースの Users という MySQL テーブルのすべての行をクエリします。その出力を ConvertMySqlRow-ToXml 関数への入力にすることができます。こうすることで、単一の XML ファイルが作成できます。
Invoke-MySqlQuery -Query ‘select * from users’ | ConvertMySqlRow-ToXml -ObjectType User -Path C:\users.xml
ConvertMySqlRow-ToXml 関数のパラメータ ObjectType と Path に注意してください。XML ツリーのため、各 MySQL 行データには親が必要です。ObjectType パラメータは、各行が表すオブジェクトの「型」を示します。
この例では、Users テーブルは、人々の名、姓、住所、市、などの情報で構成されています。これらはすべてユーザーであるため、ObjectType は User となっています。Path パラメータで、XML ファイルを作成したい場所を指定します。
すべて問題がなければ、C:\Users.xml に次のようなファイルが作成されます。
MySQL テーブルからの XML 出力の例
MySQL から JSON へ
MySQL データを XML 形式に変換したのと類似の変換プロセスで JSON への変換ができます。前と同様、ドットソース形式での読み込みを行います。
. C:\ConvertMySqlRow-ToJson.ps1
次に、Invoke-MySqlQuery コマンドレットを使用して MySQL テーブルの行をクエリし、今回はその出力を ConvertMySqlRow-ToJson 関数に渡し、結果の JSON ファイルを作成する場所のパスを指定します。
Invoke-MySqlQuery -Query ‘select * from users’ | ConvertMySqlRow-ToJson -Path C:\users. json
これで、C:\Users.json に次のように見えるファイルができます。このイメージは最初の MySQL 行データだけを示していますが、他の行もこのファイルにあります。
PowerShell を使用してデータを変換する方法の詳細は、無料ホワイトペーパー(英語) をご参照ください。
ヒント#3 - XML スキーマを構築する方法
XML スキーマは単なるテキストファイルなので、作成する方法はいくつかあります。テキストエディタを使って手作業で作成することも、コードを使用してプログラムで作成することもできます。ここでは、XSD(XMLスキーマ定義)を構築し、XML ファイルをコードで、具体的には Windows PowerShell で、検証したいと思います。
ネイティブにサポートされているわけではありませんが、PowerShell サーバーは、Microsoft の .NET Framework の基本構造を使用することができます。.NET言語には、XSD を構築する機能と、既存の XML ファイルから XSD を推測する機能があります。
PowerShell を使用したXMLスキーマの構築
上では、既存の XML ファイルを読み込み、そのファイルからスキーマを推測(XSD)し、新しい XSD ファイルを作成してから新しいスキーマを記述しています。開発者でない方は、これを見てひるんでしまうかもしれませんが、PowerShell のスクリプトと関数を使用して XML ファイルからスキーマを構築することが目的なら、この中身を把握する必要はありません。
すべてのコードが単一の PowerShell 関数にまとめられており、シンプルに読み取るXMLファイルとアウトプットのスキーマファイルを指定するだけですみます。これは、XML ファイルに変更を加えた場合、ファイルの整合性が保たれていることを確認するために変更後の XML ファイルをテストするために利用できます。
シンプルなXMLスキーマ作成
PowerShell を使用して既存の XML ファイルから XSD スキーマを簡単に構築するために最初にすることは、XML ファイルを読み込み、XSD を作成してファイルに保存するために必要なすべてのコードを含む既存の PowerShell スクリプトをダウンロードすることです。
このスクリプトは Adam Bertram の Github リポジトリにあります。New-XmlSchema.ps1 スクリプトをコンピュータにダウンロードして保存することができます。
スクリプトを使用するには、PowerShell Community Extensions の要件を満たす必要があります。このモジュールには多くの便利な関数がありますが、Test-Xml 関数は必須です。Test-Xml 関数は XM Lファイルに対してスキーマを検証するために使用する関数ですが、 New-XmlSchema.ps1 スクリプトでも使います。
最初の手順としてモジュールをダウンロードしてインストールしたら、次に、PowerShell バージョン4以降を実行している Windows コンピュータで、PowerShell コンソールを開き、New-XmlSchema.ps1 スクリプトを現在のセッションにドットソース形式で読み込みます。このスクリプトは、スキーマを簡単に作成できる New-XmlSchema 関数を使用しています。
次に、スキーマを作成する既知の良質な XML ファイルを指定する必要があります。この例では、ある業務アプリケーションで使われているさまざまなユーザーの住所氏名データがから成る、C:\ の users.xml という XML ファイルを使います。
XML ファイルの例
あとは、New-XMLSchema 関数を実行してスキーマ XSD ファイルを作成するだけです。
XSDスキーマの作成
XSD を開くことで、XSD が作成されたことが確認できます。XML スキーマの詳細については、無料ホワイトペーパー、Validating your Critical Data with PowerShell を参照してください。
PowerShell による自動化
ここまで、PowerShell がどう活用できるかについて説明しました。次のステップとして、タスク、ファイル転送、データセキュリティを自動化するためにこのツールを使用することを検討してはどうでしょうか。どう自動化できるかがわかっていると、IT予算の引き締めやIT部門の作業量増大などがあったときも対策を講じられます。ミスを最小限に抑え、予算枠内に抑えながら作業の自動化、ファイル転送、 データ保護といったニーズを満たすために、PowerShell は重要な役割を果たします。
Adam Bertram
Adam Bertram is a 20-year veteran of IT. He’s currently an automation engineer, blogger, independent consultant, freelance writer, author, and trainer. Adam focuses on DevOps, system management, and automation technologies as well as various cloud platforms. He is a Microsoft Cloud and Datacenter Management MVP and efficiency nerd that enjoys teaching others a better way to leverage automation.