(私の謙虚な意見では) 最も複雑でない解決策は、サブルーチンを使用してset str
. 遅延拡張のレベルが 1 レベル以上深くなると、深刻な脳損傷を引き起こす傾向があります。ああ、あなたはおそらくset str
次のようなことをすることであなたの行を修正することができます
call call call set str=%%%%str:%%tobereplaced%%=%replacewith%%%%%
...または類似。脳の損傷について私が言っていることがわかりますか?再帰に従うのは難しいです。
そこで、私の解決策を提案します。また、作業中に別の潜在的な問題を 1 つまたは 2 つ修正しました。*.txt を再帰的に検索しているので、for
ループがサブディレクトリ内で見つけたテキスト ファイルを処理できるようにしました。私はこれをテストしていないので、グロテスクなエラーが発生した場合はお知らせください。
@echo off
setlocal enabledelayedexpansion
set replacewith=whatever
for /r %%g in (*.txt) do (
set newfile=%%~dpng.new%%~xg
for /F "tokens=3 delims=<>" %%i in ('findstr "volumelabel" "%%g"') do (
set "tobereplaced=%%i"
echo %%~nxg has !tobereplaced! to be replaced by %replacewith%
rem combining your for loops this way makes the second only fire if the first is true
rem using "findstr /n" in your for loop preserves blank lines
for /F "delims=" %%a in ('findstr /n "^" "%%g"') do (
rem ...but you have to strip off the line numbers
set "str=%%a" && set "str=!str:*:=!"
rem "call :repl" to work around the delayed expansion conundrum
call :repl "!str!" "!tobereplaced!" "%replacewith%" str
echo !str!>>!newfile!
)
)
)
goto :EOF
:repl <line> <find> <replace> <var>
setlocal enabledelayedexpansion
set "line=%~1"
set "line=!line:%~2=%~3!"
set "%4=%line%"
goto :EOF
警告: テキスト ファイルに感嘆符、等号、またはカラットが含まれている場合、textfile.new.txt に変換されない可能性があります。
価値があるのは、私があなたの立場にあった場合、バッチファイルを使用する代わりに、おそらくsedを使用することです(必要なのはバイナリだけです)。スクリプトも必要ありません。次のようなワンライナーとして実行できます。
for /r %I in (*.txt) do sed -r "s/volumelabel/replacement/ig" "%I" > "%~dpnI.new%~xI"
ところで、表記の種類のhelp for
説明については、 の最後の数ページを参照してください。%~dpnI