複数のテキストファイル内にある文字列を置き換えるには、一括処理するツールがあると便利である。PowerShellを利用することで、テキスト処理を自動化させることができる。置き換え文字列の指定には、固定文字列だけでなく、正規表現を使用することもできる。
対象:Windows PowerShell
単一のテキストファイルに含まれる特定の文字列を置き換えるだけならば、メモ帳などの標準的なテキストエディタを利用するだけでも十分に対応可能だ。しかし対象となるファイルが多数ある場合、これを1つ1つ手作業で変換しなければならないのでは、やはり手間だし、人為的な間違いや漏れが発生する可能性がある。
そこで、本稿ではPowerShellスクリプトを利用して、複数フォルダ/ファイルにまたがるファイルに含まれる文字列を一括置換する方法を紹介する。本サンプルを使えば、コマンド1つで特定のフォルダの配下の全ファイルをまとめて置換処理できる。また、置き換え規則には正規表現を使用できるので、より複雑な編集を行いたいといった場合にも、十分応用が利くだろう(PowerShellで正規表現を利用する方法については今後、別TIPSで紹介する)。
PowerShellを利用するには、あらかじめシステムにユーザー自身がインストールしておく必要があります。具体的なインストール方法については「PowerShellをインストールする」を参照してください。
まずはテキストエディタ(メモ帳でも何でもよい)を開き、以下のコードを入力してほしい。なお「#」で始まる行は、コードの意味を解説するためのコメント部分なので、省略してもよい。コメントにはスクリプトの簡単な説明を入れておいた。
※ファイル:FileReplace.ps1
# スクリプトファイルのパラメータを宣言(先頭から「置換前の文字列」
#「置換後の文字列」「変換対象のフォルダ」「変換後のファイルの保存先」
#「テキストファイルの文字コード」)
param(
[String]$from,
[String]$to,
[String]$in = "c:\tmp\Convert",
[String]$out = "c:\tmp\Converted",
[String]$encoding = "Shift_JIS"
)
# 引数$encodingから、文字コードを表すEncodingオブジェクトを生成
$enc = [Text.Encoding]::GetEncoding($encoding)
# 与えられたパス(c:\tmp\Convert)から合致するファイルリスト
# を再帰的(-recurse)に取得
Get-ChildItem $in -recurse |
# 取得したファイルを順番に処理
ForEach-Object {
# 取得したオブジェクトがファイルの場合のみ処理(フォルダの場合はスキップ)
if($_.GetType().Name -eq "FileInfo"){
# 変換元ファイルをStreamReaderオブジェクトで読み込み
$reader = New-Object IO.StreamReader($_.FullName, $enc)
# 保存先のパス、保存先の親フォルダのパスを生成
$o_path = $_.FullName.ToLower().Replace($in.ToLower(), $out)
$o_folder = Split-Path $o_path -parent
# 保存先のフォルダが存在しない場合にフォルダを自動生成
if(!(Test-Path $o_folder)){
[void][IO.Directory]::CreateDirectory($o_folder)
}
# 保存先ファイルをStreamWriterオブジェクトでオープン
$writer = New-Object IO.StreamWriter($o_path, $false, $enc)
# 変換元ファイルを順に読み込み、保存先ファイルに書き込み
while(!$reader.EndOfStream){
#$writer.WriteLine($reader.ReadLine().Replace($from, $to))
$str = $reader.ReadLine() -ireplace $from, $to
$writer.WriteLine($str)
}
# ファイルをすべてクローズ
$reader.Close()
$writer.Close()
}
}
PowerShellスクリプトの実行ファイルは拡張子を「.ps1」とする必要がある。ファイル名自体は何でも構わないが、ここでは「FileReplace.ps1」という名前で保存しておこう。
コード全体の流れについてはリスト内のコメントをご覧いただくとして、ここで注目してほしいのは、次の点だ。
-creplace/-ireplace演算子はPowerShellで提供される演算子の1つで、一般的な構文は以下のとおりだ。
文字列 -creplace 置換前の文字列,置換後の文字列
文字列 -ireplace 置換前の文字列,置換後の文字列
どちらも文字列に含まれる特定の部分文字列を置き換え処理することができるが、-creplace演算子は大文字/小文字を厳密に区別するのに対して、-ireplace演算子は大文字/小文字を区別しない。
今回のサンプルスクリプトでは、テキストファイルから1行ずつ読み込んだ文字列を、指定された引数$from、$toに基づいて置き換え処理したものを、出力先のファイルに書き込んでいる。今回は-ireplace関数を使用しているので、大文字/小文字を区別しない置換が行われるが、もしも大文字/小文字を厳密に区別したければ-creplace演算子で置き換えればよい。
FileReplace.ps1を実行するには、PowerShellのプロンプトを開いたうえで、以下のようにコマンドを実行すればよい*。また利用に当たっては、「c:\tmp\Convert」フォルダ配下に変換対象のテキストファイルが、変換後のファイルの保存先として「c:\tmp\Converted」フォルダが存在することを確認しておいてほしい。
PS > ./FileReplace.ps1 "Windows PowerShell" "PowerShell"
PowerShellでスクリプトファイルを実行する場合には、あらかじめいくつかの設定を行っておく必要がある。詳細については、「Windows PowerShellコマンド&スクリプティング入門(後編)」を参照していただきたい。
エラーが表示されずにスクリプトが終了し、かつ、所定のフォルダ(ここでは「c:\tmp\Converted」)に変換後のファイルが保存されていれば成功だ。また、配下のテキストに含まれる「Windows PowerShell」という文字列が「PowerShell」に置き換わっていることを確認してみよう。
この例では第3〜5引数を省略しているが(デフォルトのままで実行している)、変換するファイルの場所を変更したり、使用しているファイルの文字コードを明示的に指定したければ、次のように「変換対象のフォルダ」「変換後のファイルの保存先」「文字コード」の順に引数を指定する。
PS > ./FileReplace.ps1 "Windows PowerShell" "PowerShell" "c:\tmp\Convert" "c:\tmp\Converted" "UTF-8"
この例では、「c:\tmp\Convert」フォルダにあるテキストファイルに対して文字列置換を行い、その結果を「c:\tmp\Converted」フォルダに保存する。また、テキストファイルは「UTF-8」として処理される。指定可能な文字コードについては、Tech TIPS「PowerShellで複数のファイルの文字コードを一括変換する」を参照していただきたい。文字コードを省略すると、ファイルの文字コードを「Shift_JIS」と見なして置換処理が行われる。
■この記事と関連性の高い別の記事
Copyright© Digital Advantage Corp. All Rights Reserved.