jeb's example 很有趣,但它很大程度上取决于添加或删除的文本的长度。我认为反直觉的结果就是 rein 所说的“如果你之前修改它,那么它将开始做奇怪的事情(重复命令等)”。
我已经修改了 jeb 的代码,以展示如何在执行批处理文件的开头随意修改可变长度的动态代码,只要有适当的填充。每次迭代都会完全替换整个动态部分。每条动态行都以不干扰的; 为前缀。由于隐含的EOL=; 选项,这方便FOR /F 剥离动态代码。
我不是寻找特定的行号,而是寻找特定的注释来定位动态代码的开始位置。这更容易维护。
我使用等号行无害地填充代码以允许扩展和收缩。可以使用以下字符的任意组合:逗号、分号、等号、空格、制表符和/或换行符。 (当然填充不能以分号开头。)括号内的等号允许代码扩展。括号后的等号允许代码压缩。
请注意,FOR /F 会去除空行。可以通过使用 FINDSTR 为每行添加行号前缀,然后在循环中去除前缀来克服此限制。但是额外的代码会减慢速度,因此除非代码依赖于空行,否则不值得这样做。
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
::*** Start of dynamic code ***
;set value=1
::*** End of dynamic code ***
echo The current value=%value%
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
call :changeBatch
==============================================================================
==============================================================================
)
================================================================================
================================================================================
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
for /f "usebackq delims=" %%a in ("%~f0") do (
echo %%a
if "%%a"=="::*** Start of dynamic code ***" (
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;set value=!newValue!
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
endlocal
)
)
) >"%~f0.tmp"
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
move /y "%~f0.tmp" "%~f0" > nul
==============================================================================
==============================================================================
)
================================================================================
================================================================================
echo The new filesize is %~z0
exit /b
上述方法可行,但如果将动态代码移到文件末尾的子例程中,事情会容易得多。代码可以不受限制地扩展和收缩,并且不需要填充。 FINDSTR 在删除动态部分时比 FOR /F 快得多。动态行可以安全地以分号作为前缀(包括标签!)。然后使用 FINDSTR /V 选项排除以分号开头的行,并且可以简单地附加新的动态代码。
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
call :changeBatch
call :dynamicCode1
call :dynamicCode2
echo The current value=%value%
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
findstr /v "^;" "%~f0"
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;:dynamicCode1
echo ;set value=!newValue!
echo ;exit /b
echo ;
echo ;:dynamicCode2
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
echo ;exit /b
endlocal
) >"%~f0.tmp"
move /y "%~f0.tmp" "%~f0" > nul
echo The new filesize is %~z0
exit /b
;:dynamicCode1
;set value=33
;exit /b
;
;:dynamicCode2
;echo extra line 1
;exit /b