批处理脚本如何做相当于“cat<< eof”的操作?

时间:2011-10-31 13:59:39

标签: batch-file

在Linux(Bash)中有一个very useful functionality用于将文字文本转储到另一个文件中,如下所示:

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

我需要的是Windows批处理脚本的等价物。我没有找到内置的这种功能,但我想我可以编写一个子程序来做它(我不想依赖于自XP以来在Windows中本身不存在的任何东西),但我是遇到麻烦。到目前为止,这是我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

所以我的要求是文本块按字面输出而不做任何改动(即我不想逃避空白行,%,!,&lt;等等)。这段代码几乎可以完成我需要的一切,除了我还没有找到一种方法来正确输出感叹号。这是我得到的输出,这不太正确:

   This is my test file
   Hope you like it.

    <got these>
    % and these %
     these too

   yeah

编辑: 对于任何想要现在有效的子程序的修改版本的人来说,这里是:

: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

2 个答案:

答案 0 :(得分:2)

您的代码在FOR循环中缺少一个endlocal 您可以通过setlocal EnableDelayedExpansion为每个循环创建一个新的本地上下文,这会在文本文件中出现更多行。

为了保留感叹号(以及插入符号),您需要切换技术 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**
)

答案 1 :(得分:2)

+1,有趣的应用程序!我修改了你的代码以获得更简单,更快的版本:

@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

我还创建了另一个看起来更像Linux版本的版本,也就是说,要复制的行在调用例程后直接放置,并且在最后复制的行之后继续执行。当然,为了实现这一点,不会通过call调用例程,而是使用goto调用例程,当例程结束时,执行goto %MYDELIM%而不是“return”({ {1}}或exit /b)。此外,因为goto :eof不能有参数,所以在调用之前在变量中定义“参数”。

goto

修改

这个新版本更快,现在适用于所有特殊情况,包括空行:

@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%