【バッチファイル】ファイル内の文字列を置換する

バッチファイルでファイル内の文字列を置換する方法です。

ソースコード

とりあえず対象ファイル名とかをベタ書きでソースコードを書いてみます。

@echo off

if exist example_replaced.txt del /q example_replaced.txt

rem for文の中で変数の値を変化させたい場合に宣言する
setlocal enabledelayedexpansion

rem ファイルの内容を一行ずつ変数aに格納して取り出す
rem "delims="は区切り文字を指定するオプションだが
rem 省略するとブランクやタブが区切り文字とみなされるので敢えて書いている
for /f "delims=" %%a in (example.txt) do (
  set line=%%a
  
  rem このように置換したい文字列を書いていく
  set line=!line:target_1=replaced_1!
  set line=!line:target_2=replaced_2!
  
  rem 出力
  echo !line! >> example_replaced.txt
)

endlocal

rem コピーした内容をexample.txtに移して一時ファイルを削除
copy /y example_replaced.txt example.txt
del /q example_replaced.txt

置換した内容を他ファイルに書き出す例しか見つからず、 置換した内容を一度別ファイルとして書き出して置換前のファイルに書き戻しています。

このあたりはもっと効率のいい方法があるかもしれません。

!が消える

setlocal enabledelayedexpansionを使うと置換対象の文字列に!が含まれていたら消えてしまうという副作用があるため、
一部サブルーチン化して``を削除します。

@echo off

if exist example_replaced.txt del /q example_replaced.txt

rem setlocal enabledelayedexpansionは削除

for /f "delims=" %%a in (example.txt) do (
  rem 置換して書き込み
  call :replace_and_write %%a
)

rem コピーした内容をexample.txtに移して一時ファイルを削除
copy /y example_replaced.txt example.txt
del /q example_replaced.txt

exit /b

rem 置換してファイルに書き込むサブルーチン
:replace_and_write
  set line=%1
  set line=%line:target_1=replaced_1%
  set line=%line:target_2=replaced_2%
  echo %line% >> example_replaced.txt
exit /b

!が消えてしまう理由については下記のサイトが詳しいです。

qiita.com

また、サブルーチンは関数のようなもので、下記のサイトを参考にしました。

maku77.github.io

対象ファイルを引数として受け取る

次に対象ファイルを引数として受け取ります。

@echo off

rem %~x1で引数のファイル名から拡張子を取得
if exist replaced%~x1 del /q replaced%~x1

for /f "delims=" %%a in (example.txt) do (
  rem 置換して書き込み
  call :replace_and_write %%a %~x1
)

rem コピーした内容をexample.txtに移して一時ファイルを削除
copy /y replaced%~x1 %1
del /q replaced%~x1

exit /b

rem 置換してファイルに書き込むサブルーチン
:replace_and_write
  set line=%1
  set line=%line:target_1=replaced_1%
  set line=%line:target_2=replaced_2%
  echo %line% >> replaced%2
exit /b

前節までのものよりは実用的になった気がします。

参考

qiita.com

jj-blues.com

qiita.com

maku77.github.io