スポンサーリンク

バッチで文字列を置換する (JScriptでテキストファイル処理)



テキストファイル中の文字列を置換する場合,
普通はエディタの置換機能を使うだろう。


しかし,それが何度も行なうルーティンになっている場合,手作業をしてはいけない。
ミスが混入しないように,毎回の置換作業をバッチに任せるべきだ。


残念ながら,Windows コマンドプロンプト(.bat)ではファイル中の文字列の置換はできない。

かわりにここでは,WSHで動くJavascriptのクローンであるJScriptを使って,プレーンテキストの処理をするバッチを作成する。



作成と言っても,下記のコードをコピペするだけ。

完成したバッチファイルをダブルクリックするだけで,置換済みの新テキストファイルが生成される。




例えば,「テスト用」の設定ファイルと,「本番用」の設定ファイルがあるとしよう。

テスト用のファイル中で「localhost」となっているのを,本番用では「192.168.0.1」のように本番サーバのIPアドレスに置き換えて記述したいとする。


設定内容に変更があるたびに毎回,

  • まずテスト用の設定ファイルを開き
  • エディタで「localhost」を「192.168.0.1」に置換し
  • 本番用のファイル名で保存し直す

という手順を踏むのは,煩雑だ。



この置換作業を一発で行なうためには,まず下記のようなバッチファイルを作成する。

ファイル名は,例えば「replace.js」のように拡張子を .js にする。

/*
   旧ファイルの文字列を置換して新ファイルに書き込む
   
   使い方
   ・最初の4つの変数の値を書き換える
   ・ダブルクリックで実行
*/


// 書き変えたい内容
var str_from  = "localhost";
var str_to    = "192.168.0.1";
var file_from = "data_local.conf";
var file_to   = "data.conf";


// 定数
var ForReading   = 1; // 読み込み
var ForWriting   = 2; // 書き込み(上書き)
var ForAppending = 8; // 書き込み(追記)


// ファイル存在チェック
var fso_r = WScript.CreateObject( "Scripting.FileSystemObject" );
if( ! fso_r.FileExists( file_from ) )
{
	WScript.Echo( "ファイルが存在しません。" );
	// 強制終了
	WScript.Quit();
}


// 新規ファイル作成
var fso_w = WScript.CreateObject( "Scripting.FileSystemObject" );
if( fso_w.FileExists( file_to ) )
{
	fso_w.DeleteFile( file_to );
}
var txt_w = fso_w.CreateTextFile( file_to );


// 旧ファイルを読み込み
var txt_r = fso_r.OpenTextFile( file_from, ForReading );
while( ! txt_r.AtEndOfStream )
{
	// 置換
	str = txt_r.ReadLine();
	str = str.replace(  new RegExp( str_from, "g" ), str_to );
	txt_w.WriteLine( str );
}


txt_r.Close();
txt_w.Close();
WScript.Echo( "置換終了" );


そして,ただこの replace.js をダブルクリックすればよい。

すると data_local.conf という元ファイルの内容を置換して,新ファイル data.conf が生成される。(同じフォルダ上に置いておくこと。)



解説

JavaScriptではファイル処理は不可能だが,WSHならば専用のオブジェクトを使ってそれが可能になる。


WSHには標準でVBScriptJScriptがある。
VBScriptでファイル処理をするための情報は巷に多くあるが,JScriptに関してはそれほど多くない。

しかし,もしJScriptで FileSystemObject の使い方を身に着ければ,JavaScriptで培ったノウハウを生かしてバッチ作成ができる。


JScriptには,一部JavaScriptと異なるコーディング作法がある。

  • alert() のかわりに,WScript.Echo() を使う。


JavaScriptは実行のためにHTML中に埋め込む必要があるが,JScriptならばファイル単体でそのまま実行して,結果を直接出力できる。

コンパイル不要だし,ブラウザもサーバも不要。

メモ帳さえあれば,ファイル処理を行なうアプリケーションが作成できる。

最も手軽なプログラミング手段の一つと言えるだろう。(OSはWindows限定になるが)


なお,UTF-8でファイル入出力したい場合は下記を参照。

jscriptで utf8なファイル出力
http://passing.breeze.cc/mt/archives/2008/05/jscript-utf8.html

おまけ

これは昔書いた,ニュートン法のスクリプト。

//初期値、許容誤差、反復回数
var x0 = 10.0;
var eps = 0.0001;
var imax = 1000;

function f( x ){ //	y = f(x)
  y = x * x; return y;
}

function df( x ){ //	y' = f'(x)
  dy = 2 * x; return dy;
}

//反復
oldx = x0;
for( i = 0; i < imax; i++ ){
  nextx = oldx - ( f( oldx ) / df( oldx ) );
  if( Math.abs( f(nextx) ) < eps )break;
  else oldx = nextx;
}

WScript.Echo( "x = " + nextx + ", f(x) = " + f(nextx) );

導関数が既知のとき,適当な初期値を与えて f(x) = 0 なる方程式の解を数値的に求める事ができる。
やはりダブルクリックだけで実行できる。

補足

HTA形式で実行する際には,WScriptが最初から使えないので

var fso_w = WScript.CreateObject( "Scripting.FileSystemObject" );

のかわりに

var fso_w = new ActiveXObject( "Scripting.FileSystemObject" );

とする。


また、一行ずつ読むのではなくてファイル全体を丸ごと読み込む ReadAll() メソッドも便利だが、利用時は必ず

	if( ! txt_r.AtEndOfStream )
	{
		str = txt_r.ReadAll();
	}

のように、ファイルの終端に達していないかどうか判定を行なうこと。

一行ずつ読み進んでいくわけでもないのに終端判定する理由は、ファイルが空の場合があるから。


ファイルが空なのに ReadAll() すると

	エラー:ファイルの最後を超えた入力を行なおうとしました。

のエラーが出る。