[英]Using FOR loop to copy code between to labels in batch file
好的,所以我經常寫批處理文件。 不久前,我問一個問題user:cmd
關於如何將正在運行的批處理文件的一部分復制到新的批處理文件中,如果您要在批處理文件中一次性使用它,它會起作用。 我的目標是從一個安裝批處理中創建多個大批處理文件。 如果他們選擇安裝,則發生的情況是批處理文件運行以下內容。
cls
setlocal EnableDelayedExpansion
color e
::Start of embedded code
set Begin=
for /F "delims=:" %%a in ('findstr /N "^:EMBEDDED_CODE" "%~F0"') do (
if not defined Begin (
set Begin=%%a
) else (
set End=%%a
)
)
::*****************************************************************************
(for /F "skip=%Begin% tokens=1* delims=[]" %%a in ('find /N /V "" "%~F0"') do (
if %%a equ %End% goto :Build-file2
echo(%%b
)) > file1.bat & goto :Build-file2
)
goto :Build-file2
:EMBEDDED_CODE Begin
CODE TO PUT INTO "file1.bat"
:EMBEDDED_CODE End
:Build-file2
cls
setlocal EnableDelayedExpansion
color e
::Start of embedded code
set Begin=
for /F "delims=:" %%a in ('findstr /N "^:EMBEDDED_CODE" "%~F0"') do (
if not defined Begin (
set Begin=%%a
) else (
set End=%%a
)
)
::*****************************************************************************
(for /F "skip=%Begin% tokens=1* delims=[]" %%a in ('find /N /V "" "%~F0"') do (
if %%a equ %End% goto :EOF
echo(%%b
)) > file2.bat & goto :EOF
)
goto :EOF
:EMBEDDED_CODE Begin
CODE TO PUT INTO "file2.bat"
:EMBEDDED_CODE End
發生的問題不是在標簽EMBEDDED_CODE Begin
和EMBEDDED_CODE End
之間復制代碼,而是在它從EMBEDDED_CODE Begin
復制的第一個FOR
循環中EMBEDDED_CODE Begin
一直到腳本的最底部,將其放入我想要的文件中,然后轉到下一個FOR
循環,使用to標簽之間的不同代碼重復該過程。 因此file1.bat
和file2.bat
都包含完全相同的代碼,但是具有所需的文件名file1.bat
和file2.bat
。
為什么您期望得到的結果與您得到的結果有所不同? FINDSTR將搜索整個文件,因此將Begin
設置為第一個代碼塊中的:EMBEDDED_CODE
的第一個匹配項,而End
設置為最后一個代碼塊中的最后一個匹配項(以最后一個值為准)。 您復制了代碼,因此當然會兩次得到相同的錯誤結果。
只需更改第二個代碼塊中的標簽,也許是:EMBEDDED_CODE2
,然后相應地調整第二個FINDSTR。 所有人都應該工作。
我經常使用略有不同的方法來最大程度地減少文件讀取量。 只需使用相同的唯一前綴修改給定嵌入式代碼塊中的所有行。 然后FINDSTR可以直接輸出所需的行,並使用FOR / F去除前綴。 您只需要前綴以與代碼開頭不匹配的字符結尾即可。
使用FOR / F讀取文件時,應謹慎啟用延遲擴展。 如果包含的嵌入式代碼將被破壞!
並啟用了延遲擴展。 (除非!
逃脫了,但這可能很痛苦)
@echo off
for %%C in (1 2) do (
for /f "tokens=1* delims=}" %%A in ('findstr /bl ":%%C}" "%~f0"') do echo(%%B
)>file%%C.bat
:1}Your first code block goes here
:1}
:1} Blank lines and indents are preserved
:1}And so are exclamation points!
:2}And here is your second code block
:2}...
echo file1.bat
echo ---------
type file1.bat
echo(
echo(
echo file2.bat
echo ---------
type file2.bat
這幾乎可以滿足您的需求。
此代碼需要讀取兩次輸入文件,首先是找到要處理的行范圍(findstr行編號),然后是提取它們。 在第二個循環中,再次使用findstr編號以避免for /f
壓縮空白行並更改行編號。
另一方面,處理了擴展文本中帶有特殊字符的問題,從而根據需要啟用和禁用延遲擴展。
也許不是最好的性能,但它似乎可以工作。 根據需要進行調整。
@echo off
setlocal enableextensions enabledelayedexpansion
call :extractEmbedded "Section1" extracted.txt
if not errorlevel 1 (
cls
type extracted.txt
)
exit /b
:extractEmbedded id outputFile
rem prepare environment
setlocal enableextensions enabledelayedexpansion
rem asume failure on execution
set "_return=1"
rem find embedded zone in current file
set "_start="
set "_end="
for /f "tokens=1 delims=:" %%l in ('findstr /n /b /c:":EMBEDDED %~1" "%~f0"') do (
if not defined _start ( set "_start=%%l" ) else ( set "_end=%%l" )
)
rem adjust lines to process
set /a "_start+=0"
set /a "_end-=1"
rem if nothing found, task done
if %_start% GEQ %_end% goto endExtractEmbedded
rem prepare file extraction
if "%_start%"=="0" (set "_skip=" ) else ( set "_skip=skip^=%_start%" )
rem extract proper area of file to output file
(for /f tokens^=^*^ %_skip%^ eol^= %%l in ('findstr /n "^" "%~f0"') do if !_start! LSS !_end! (
setlocal disabledelayedexpansion
set "_line=%%l"
setlocal enabledelayedexpansion
echo(!_line:*:=!
endlocal & endlocal
set /a "_start+=1"
))>"%~2"
rem everything ok
set "_return=0"
:endExtractEmbedded
rem exit with errorlevel
endlocal & exit /b %_return%
:EMBEDDED Section1
This is a section; of embedded!!! code
that needs to be extracted to generate
a new file to be processed.
TEST: !""$%&/()=?¿^*[];,:-\|
:EMBEDDED Section1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.