How can a batch script do the equivalent of “cat << eof”?

后端 未结 2 1301
醉酒成梦
醉酒成梦 2020-12-29 17:49

In Linux (Bash) there is a very useful functionality for dumping literal text out to another file like this:

cat > see.txt << EOF
contents going int         


        
相关标签:
2条回答
  • 2020-12-29 18:21

    +1, Interesting application! I modified 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 that looks more like the Linux version, that is, the lines to copy are placed directly after invoking the routine, and the execution continue after the last copied line. Of course, to make this possible the routine is not invoked via call, but entered with a goto, and when the routine ends it execute a goto %MYDELIM% instead of a "return" (exit /b or goto :eof). Also, because a goto can not have parameters, the "parameters" are defined in variables before the invocation.

    @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 empty 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
    
    0 讨论(0)
  • 2020-12-29 18:25

    In your code is missing a single endlocal in your FOR-loop.
    You create for each loop a new local-context through the setlocal EnableDelayedExpansion, this will explode with some more lines in your text file.

    And to preserve the exclamation marks (and also the carets) you need the toggling technic 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**
    )
    
    0 讨论(0)
提交回复
热议问题