BatchIT

【文字列置換え】バッチだと不具合がでるので、WSHで対応してみる

バッチを使用して特定のファイルの文字列置換えをやってみたのですが、正しく動作してくれません。 それは、置換えの入力文字、もしくは、置き換え前の元となるファイルに「!」文字が含まれていた時に、それを置き換え後ファイルに反映できないという点です。 おそらく特殊文字として判定されてしまっているのですが、どんな方法を使っても解決できなかったため、WSHを使用することにしました。 WSHとは…

Windows Script Host(ウインドウズ・スクリプト・ホスト)とは、Microsoft Windowsにおいてテキストファイルに記述したスクリプトを実行するスクリプト実行環境である。WSHと略される。かつてはWindows Scripting Hostと称した。 Windows 98から搭載された。Unixにおけるシェルスクリプトや、MS-DOSにおけるバッチファイルと似た位置づけの技術である。(以下略)

Wikipedia

標準で用意されたJScriptを利用して、文字列の置き換えを行います。 今回は、PHPの設定ファイルである「.htaccess」のクリックジャッキング対策であるコード部分をコメントアウトする、という動作をさせます。 (.htaccessの中に「!」文字が含まれており、バッチを使用できなかったためです)

var str_from  = "Header always append X-Frame-Options SAMEORIGIN";
var str_to    = "# Header always append X-Frame-Options SAMEORIGIN";
var file_from = "C:/repos/setup/app/webroot/.htaccess";
var file_to   = "C:/repos/setup/app/webroot/.htaccesstmp";

// 定数
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 )
{
	// 置換r
	str = txt_r.ReadLine();
	str = str.replace(  new RegExp( str_from, "g" ), str_to );
	txt_w.WriteLine( str );
}

これを「xxxx.js」という形式で保存して、ダブルクリックすると動作させることができます。 しかし、これでは書き換えされた「.htaccesstmp」という別のファイルが作成されるだけのため、この処理の後に「.htaccess」を削除し、「.htaccesstmp」のファイル名を「.htaccess」に変更するという処理を書き足します。 http://wsh.style-mods.net/ このサイトを参考に、まずはファイルを削除する処理を書き足します。 が、動作しません…またか。 バッチでは、同じような処理を書いたことがあるので、何か打つ手はないかと調べてみると

@if(0)==(0) Echo Off

Echo Windows バッチによる前処理

Rem JScript の呼び出し
CScript //NoLogo //E:JScript "%~f0" %*

Echo Windows バッチによる後処理

Pause
Exit /b

@end

// ココから JScript

WScript.echo("WSH JScript による処理");

http://neos21.hatenablog.com/entry/2016/10/28/211531 引用) ありました! バッチの中にWSHを混合させて書く方法があるようです。 ということで、さっそく組み合わせてみる。

@if(0)==(0) Echo Off

rem Windows バッチによる前処理

Rem JScript の呼び出し
CScript //NoLogo //E:JScript "%~f0" %*

rem Windows バッチによる後処理
     if EXIST C:\repos\setup\app\webroot\.htaccess del C:\repos\setup\app\webroot\.htaccess
	 RENAME C:\repos\setup\app\webroot\.htaccesstmp .htaccess
Pause
Exit /b

@end

// ココから JScript
// 書き変えたい内容
var str_from  = "Header always append X-Frame-Options SAMEORIGIN";
var str_to    = "# Header always append X-Frame-Options SAMEORIGIN";
var file_from = "C:/repos/setup/app/webroot/.htaccess";
var file_to   = "C:/repos/setup/app/webroot/.htaccesstmp";

// 定数
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 )
{
	// 置換r
	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( "置換終了" );

何にも考えず、それぞれのコードを指定された場所に張り付けただけですが、しっかりと動作しました。 便利ですねぇ。 このファイルは、初期状態でバッチを実行しているので、拡張子はもちろん「bat」です。 「xxxx.bat」という形式で保存し、実行時にはダブルクリックしてください。 これで今後は、文字列置換えに悩まされることはなさそうです。