对于多个文件,将Batch替换为Batch

时间:2016-06-19 10:32:14

标签: windows batch-file cmd

我尝试使用建议的脚本here

我的目标是能够将脚本重用于多个文件。 我有一个文件包含这个脚本,另一个文件只是用不同的参数多次触发脚本。

ReplaceString.bat

@echo off
REM -- Prepare the Command Processor --
SETLOCAL ENABLEEXTENSIONS
SETLOCAL DISABLEDELAYEDEXPANSION

::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
:$changed 20100115
:$source http://www.dostips.com
if "%~1"=="" findstr "^::" "%~f0"&GOTO:EOF
for /f "tokens=1,* delims=]" %%A in ('"type %3|find /n /v """') do (
    set "line=%%B"
    if defined line (
        call set "line=echo.%%line:%~1=%~2%%"
        for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) ELSE echo.
)

让我们说:

foo.bat

set oldString=foo
set newString=newFoo

ReplaceString.bat %oldString% %newString% someFile.txt >someFile.txt

ReplaceString.bat %oldString% %newString% someFile2.txt >someFile2.txt

但无论出于何种原因,执行第一次调用后执行都会停止。

我尝试用ReplaceString.batSTART拨打CALL foo.bat,尝试不将输出重定向到文件,但每次我都得到相同的结果。

我希望能够强制ReplaceString.bat继续投放,或CALL不要退出。

修改 我错误地认为脚本过早地结束了,但实际发生的是,我只是没有收到输出到我的控制台,命令确实运行NullReferenceException命令。 我的脚本的另一个问题是将输出重定向回输入文件,通过将输出重定向到临时文件并在调用结束后将其替换为原始文件来修复。

2 个答案:

答案 0 :(得分:4)

ReplaceString.bat可以帮助你在foo.bat中以有问题的方式使用;你应该改变如下:

set oldString=foo
set newString=newFoo

CALL ReplaceString.bat %oldString% %newString% someFile.txt  >someFileX.txt

CALL ReplaceString.bat %oldString% %newString% someFile2.txt >someFile2X.txt
  1. 请注意˙CALL˙ command 从另一个批处理程序调用
  2.   

    调用第二个批处理文件
    CALL命令将启动新的批处理文件上下文以及任何指定的参数。什么时候结束   到达第二个批处理文件(或者如果使用EXIT),控制   将在最初的CALL语句之后返回。

         

    参数可以作为简单字符串或使用变量传递。

    1. 请注意,如果您将ReplaceString.bat输出重定向到要在ReplaceString.bat %oldString% %newString% someFile.txt >someFile.txt中解析的同一文件,则redirection operator >首先清空输出文件以便被调用的脚本无需解析(或解析空文件)...使用不同的输入和输出文件,如上面的代码示例所示。

答案 1 :(得分:3)

首先,我建议将 ReplaceString.bat 更改为:

@echo off
rem -- Prepare the Command Processor --
setlocal EnableExtensions DisableDelayedExpansion

::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
:$changed 20100115
:$source http://www.dostips.com
if "%~1"=="" %SystemRoot%\System32\findstr.exe "^::" "%~f0" & goto :EOF
for /f "tokens=1,* delims=]" %%A in ('"type %3|%SystemRoot%\System32\find.exe /n /v """') do (
    set "line=%%B"
    if defined line (
        call set "line=echo.%%line:%~1=%~2%%"
        for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) else echo.
)
endlocal

setlocal 的每次使用都会导致创建整个环境表的副本,同时将指针推送到堆栈上的上一个环境表,推送命令扩展的当前状态和堆栈上的延迟扩展的当前状态并推送也是堆栈上的当前目录路径。只需一个 setlocal 即可启用命令扩展(默认情况下已启用)并禁用延迟扩展(默认为禁用)。

Windows命令处理器恢复环境,就像在批处理文件处理时到达退出点时启动批处理文件一样。但是,对每个 setlocal 使用相应的 endlocal 命令是个好主意。

使用完整路径和文件扩展名调用 findstr 查找也很好,因为在环境变量 PATH 中很容易发生是%SystemRoot%\System32之前包含的文件夹路径,其中还包含从Unix移植到Windows的find.exefindstr.exe,但当然工作方式不同,或find.bat或{{{ 1}},文件扩展名在环境变量 PATHEXT 中定义。

但是,在处理 foo.bat 时从未调用过findstr第二行的主要原因是:

ReplaceString.bat的第一行没有命令调用

因此 foo.bat 的处理继续 ReplaceString.bat ,永远不会回到 foo.bat 因为没有调用其他批处理文件。

foo.bat

需要以下几行
ReplaceString.bat

有关详细信息,请参阅我在How to call a batch file in the parent folder of current batch file?

上的回答

并且无法将输出重定向到输入文件。必须将输出重定向到单独的文件,然后将其移到输入文件上。

再补充一点:

ReplaceString.bat 适用于所有文件内容,但不适用于所有文件内容。

例如,只需稍微改进 ReplaceString.bat 的版本

set oldString=foo
set newString=newFoo

call ReplaceString.bat %oldString% %newString% someFile.txt >someFile_1.txt
move /Y someFile_1.txt someFile.txt

call ReplaceString.bat %oldString% %newString% someFile2.txt >someFile_2.txt
move /Y someFile_2.txt someFile2.txt

会导致意外的错误消息

  

系统找不到指定的路径。

并且文件ReplaceString.bat dostips mytips ReplaceString.bat >ReplaceString.txt 已按预期在第11行中将ReplaceString.txt替换为dostips,但第12行缺少mytips,缺少批处理文件中的第13行完全在输出文本文件中。

有关替代方案,请参阅How can you find and replace text in a file using the Windows command-line environment?