How does a script package fulfill the equivalent of "cat << eof"?

Linux (Bash) has some very useful functionality for dumping literal text into another file as follows:

 cat > see.txt << EOF contents going into my file EOF 

What I need is the equivalent for a windows script package. I did not find such functionality built-in, but I thought I could write a subroutine for this (I do not want to rely on something that was not originally on Windows with XP), but I had problems. Here is what I have so far through various sources :

 call:catMyChunk myCustomText c:\see.txt exit /b goto:myCustomText This is my test file Hope you like it. <got these> % and these % ! these too yeah :myCustomText :catMyChunk ::Should call this function with 2 args, MYDELIM and outFile.txt ::where is to be catted to outFile.txt ::and text starts with <beginning of line>goto:MYDELIM ::and ends with <beginning of line>:MYDELIM set searchStart=goto:%~1 set searchStop=:%~1 set outFile=%~2 set startLine=0 set endLine=0 for /f "delims=:" %%a in ('findstr -b -n !searchStart! %~dpnx0') do set "startLine=%%a" for /f "delims=:" %%a in ('findstr -b -n !searchStop! %~dpnx0') do set "endLine=%%a" set /a linesLeftToRead=%endLine% - %startLine% del %outFile% if "%linesLeftToRead%" LEQ "0" ( echo Error finding start and end delmieters for %searchStop% in catMyChunk routine exit /B 1 ) setlocal DisableDelayedExpansion for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do ( set "oneLine=%%a" setlocal EnableDelayedExpansion set "oneLine=!oneLine:*:=!" set /a linesLeftToRead-=1 if !linesLeftToRead! LEQ 0 exit /B echo(!oneLine!>>%outFile% ) goto: EOF 

So, my requirement is that a piece of text is displayed literally without any changes (i.e. I do not want to run empty lines,%,!, <, Etc.). This code does almost everything I need, except that I have not found a way to get the exclamation points correctly. Here is the result that I get, which is not entirely correct:

  This is my test file Hope you like it. <got these> % and these % these too yeah 

Edit: For those who want to change a modified version of a routine that now works, here it is:

 :catMyChunk ::Should call this function with 2 args, MYDELIM and outFile.txt ::where is to be catted to outFile.txt ::and text starts with <beginning of line>goto:MYDELIM ::and ends with <beginning of line>:MYDELIM set searchStart=goto:%~1 set searchStop=:%~1 set outFile=%~2 set startLine=0 set endLine=0 for /f "delims=:" %%a in ('findstr -b -n !searchStart! %~dpnx0') do set "startLine=%%a" for /f "delims=:" %%a in ('findstr -b -n !searchStop! %~dpnx0') do set "endLine=%%a" set /a linesLeftToRead=%endLine% - %startLine% del %outFile% if "%linesLeftToRead%" LEQ "0" ( echo Error finding start and end delmieters for %searchStop% in catMyChunk routine exit /B 1 ) setlocal DisableDelayedExpansion for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do ( set "oneLine=%%a" set /a linesLeftToRead-=1 setlocal EnableDelayedExpansion set "oneLine=!oneLine:*:=!" if !linesLeftToRead! LEQ 0 exit /B echo(!oneLine!>>%outFile% endlocal ) endlocal goto: EOF 
+4
source share
2 answers

Your code is missing one endlocal in your FOR loop.
You create a new local context for each loop through setlocal EnableDelayedExpansion , this will explode with a few more lines in your text file.

And to save exclamation points (as well as carriages), you need technical equipment DOS batch files: how to read a file?

 setlocal DisableDelayedExpansion for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do ( set "oneLine=%%a" setlocal EnableDelayedExpansion set "oneLine=!oneLine:*:=!" set /a linesLeftToRead-=1 if !linesLeftToRead! LEQ 0 exit /B echo(!oneLine!>>%outFile% **endlocal** ) 
+2
source

+1, an interesting application! I changed your code for a simpler and faster version:

 @echo off call :catMyChunk myCustomText see.txt exit /b goto:myCustomText This is my test file Hope you like it. <got these> % and these % ! these too yeah :myCustomText :catMyChunk ::Should call this function with 2 args, MYDELIM and outFile.txt ::where is to be catted to outFile.txt ::and text starts with <beginning of line>goto:MYDELIM ::and ends with <beginning of line>:MYDELIM setlocal DisableDelayedExpansion set searchStart=goto:%~1 set searchStop=:%~1 set outFile=%~2 if exist %outFile% del %outFile% set copyFlag=No echo No> copyFlag for /f "delims=" %%a in (%~f0) do ( set "oneLine=%%a" setlocal EnableDelayedExpansion if !copyFlag! == No ( if !oneLine! == %searchStart% echo Yes> copyFlag ) else ( if !oneLine! == %searchStop% ( echo No> copyFlag ) else ( echo/!oneLine!>> %outFile% ) ) endlocal set /p copyFlag=< copyFlag ) endlocal goto :eof 

I also created another version, which is more similar to the Linux version, that is, the lines that need to be copied are placed immediately after calling this procedure, and execution continues after the last copied line. Of course, to make this possible, the subroutine is not called via call , but is entered using goto , and when the procedure ends, it executes goto %MYDELIM% instead of "return" ( exit /b or goto :eof ). Also, since a goto cannot have parameters, "parameters" are defined in variables before the call.

 @echo off set searchStop=EndOfMyText set outFile=see.txt goto :catMyChunk EndOfMyText This is my test file Hope you like it. <got these> % and these % ! these too yeah :EndOfMyText exit /b :catMyChunk ::Before JUMP to this "function" define 2 vars: searchStop and outFile ::where is to be catted to %outFile% ::and text starts with goto :catMyChunk %searchStop% ::and ends with :%searchStop% setlocal DisableDelayedExpansion set searchStart=goto :catMyChunk %searchStop% if exist %outFile% del %outFile% set copyFlag=No echo No> copyFlag for /f "delims=" %%a in (%~f0) do ( set "oneLine=%%a" setlocal EnableDelayedExpansion if !copyFlag! == No ( if /I !oneLine! == !searchStart! echo Yes> copyFlag ) else ( if !oneLine! == :%searchStop% ( echo No> copyFlag ) else ( echo/!oneLine!>> %outFile% ) ) endlocal set /p copyFlag=< copyFlag ) endlocal goto %searchStop% 

EDIT

This new version is even faster and now works with all special cases, including blank lines:

 :catMyChunk ::Should call this function with 2 args, MYDELIM and outFile.txt ::where is to be catted to outFile.txt ::and text starts with <beginning of line>goto:MYDELIM ::and ends with <beginning of line>:MYDELIM setlocal EnableDelayedExpansion set searchStart=goto:%~1 set searchStop=:%~1 set outFile=%~2 if exist %outFile% del %outFile% findstr /n ^^ "%~f0" > pipeline.txt call :seekMyChunk < pipeline.txt del pipeline.txt exit /B :seekMyChunk set oneLine=:EOF set /P oneLine= if !oneLine! == :EOF goto startNotFound set oneLine=!oneLine:*:=! if not !oneLine! == %searchStart% goto seekMyChunk :catNextLine set oneLine=:EOF set /P oneLine= if !oneLine! == :EOF goto stopNotFound set oneLine=!oneLine:*:=! if !oneLine! == %searchStop% goto :eof echo/!oneLine!>> %outFile% goto catNextLine :startNotFound echo Error finding start delimiter for %searchStart% in catMyChunk goto :eof :stopNotFound echo Error finding stop delimiter for %searchStop% in catMyChunk goto :eof 
+2
source

All Articles