バッチ ファイルには複数の制限があるため、汎用的なソリューションを作成することは困難です。このため、私は常に、特定の問題の特定の要件を最初に満たそうとします。これが可能であれば、現在誰かから要求されていない他の同様の問題に対して、より一般的な解決策を提供するという Batch の制限は問題になりませんよね?
以下のバッチ ファイルは、大文字と小文字を区別して、ある文字列を別の文字列に置き換えます。これは非常に高速ですが、対象の文字列を含め、大文字と小文字の組み合わせが異なる複数回記述された元の文字列を含む行で失敗します。この要件を持つほとんどのユーザーにとって、この方法で十分だと思います。
@echo off
setlocal EnableDelayedExpansion
set /P "file=Enter file name: "
set /P "OldStr=Enter original text: "
set /P "NewStr=Enter new text: "
rem Get list of numbers of matching lines to replace
set n=0
for /F "delims=:" %%a in ('findstr /N /C:"%OldStr%" "%file%"') do (
set /A n+=1
set replace[!n!]=%%a
)
if %n% equ 0 (
echo Original text not found in file
goto :EOF
)
set /A n+=1
set replace[%n%]=0
rem Process all lines in the file
setlocal DisableDelayedExpansion
set i=1
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%file%"') do (
set line=
set "line=%%b"
setlocal EnableDelayedExpansion
rem If this line have the original string...
for %%i in (!i!) do if %%a equ !replace[%%i]! (
rem ... replace it and advance to next matching line number
echo !line:%OldStr%=%NewStr%!
endlocal & set /A i=%%i+1
) else (
echo(!line!
endlocal
)
)) > "%file%_new.txt
rem If you want to replace the original file, remove REM from next line:
REM move /Y "%file%_new.txt" "%file%"
たとえば、この入力ファイルは次のとおりです。
This line is not changed: Rise.
No problem with special characters: & | < > ! " ^
This line is changed: rise
This line is not changed: RISE
This line is incorrectly changed: Rise & rise
「rise」を「New Text」に置き換えると、次のようになります。
This line is not changed: Rise.
No problem with special characters: & | < > ! " ^
This line is changed: New Text
This line is not changed: RISE
This line is incorrectly changed: New Text & New Text