microsoft batch:将文本文件读入变量并放入另一个文件

时间:2017-03-06 16:41:41

标签: batch-file cmd io

我对批处理不太熟练,所以我真的很挣扎。

我有两个文本文件,基本上我试图将一个文件的内容插入另一个文件。 基本上,一个文件描述对象的几何形状,另一个文件描述该几何体。

到目前为止,我的基本方法是将geomtry文件读入变量:

setlocal EnableDelayedExpansion
set LF=^


rem ** The two empty lines are necessary
set "content="

for /f "delims=" %%x in (%replace%) do (
   set "content=!content!%%x"
)

echo(!content!
endlocal

然后查看我的显示程序文件以获得预定义的“标记”:

set "search=noGeometrySpecified"

然后将用一个非常长的字符串替换:content

我目前遇到的一个问题是setlocal ... endlocal定义了某种范围(正如我所说的批处理脚本非常不确定),它不允许在我的搜索和替换中访问content我脚本的一部分。但我不能让它与他们分享某种范围。

据我所知,我的脚本的各个部分(加载整个几何文件,以及在显示程序文件中搜索和替换)都能正常工作,但是我不能让它们互相交谈。

这是我的完整代码:

@echo off &setlocal
set "search=noGeometrySpecified"
set "replace=test_geom/\EIN.b18"


setlocal EnableDelayedExpansion
set LF=^


rem ** The two empty lines are necessary
set "content="

for /f "delims=" %%x in (%replace%) do (
   set "content=!content!%%x"
)

echo(!content!
endlocal


set "textfile=index.html"
set "newfile=index-active.html"
(for /f "delims=" %%i in (%textfile%) do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    set "line=!line:%search%=%content%!"
    echo(!line!
    endlocal
 ))>"%newfile%"

 pause

2 个答案:

答案 0 :(得分:1)

@echo off
setlocal EnableDelayedExpansion
set "search=noGeometrySpecified"
set "replace=test_geom/\EIN.b18"
set "content="

for /f "delims=" %%x in (%replace%) do (
   set "content=!content!%%x"
)

echo(!content!

set "textfile=index.html"
set "newfile=index-active.html"
(for /f "delims=" %%i in (%textfile%) do (
    set "line=%%i"
    set "line=!line:%search%=%content%!"
    echo(!line!
 ))>"%newfile%"

 pause

嗯 - 似乎是希望随意洒上setlocalendlocal的案例。

setlocal需要启用delayedexpansion(使用!var!来提取变量的运行时值,其中%var%提取分析时间值)。它会一直有效,直到达到endlocal或文件结尾。

endlocal恢复上次匹配的delayedexpansion执行时的环境和setlocal状态。重要的是,它支持自上次setlocal以来所做的任何环境变化。

因此,原始代码中endlocal之后的echo(!content!会退回刚刚对content的值进行的分支,因此它将恢复为原始值没有

由于您希望保留其值以便在代码的其余部分中使用,因此必须删除endlocal

由于delayedexpansion已被调用且endlocal不再删除,因此无需在for循环内重新调用它,因此新的{{1}可以删除匹配的setlocal

似乎没有理由建立endlocal变量,因为它没有被使用,所以我也处理了它。

关于在与LF相同的行上调用setlocal或作为单独行的个人偏好。我更喜欢单独的一行。

答案 1 :(得分:1)

正如Magoo中已解释的their answer,您错误地放置了setlocalendlocal

以下是重写脚本的另一种方法 - 解释如下:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "search=noGeometrySpecified"
set "replace=test_geom/\EIN.b18"

set "content="
for /F "usebackq delims=" %%x in ("%replace%") do (
   set "item=%%x"
   setlocal EnableDelayedExpansion
   for /F "delims=" %%a in ("content=!content!!item!") do (
       endlocal
       set "%%a"
   )
)
setlocal EnableDelayedExpansion
echo(!content!
endlocal

set "textfile=index.html"
set "newfile=index-active.html"
> "%newfile%" (
    for /F "usebackq delims=" %%i in ("%textfile%") do (
        set "line=%%i"
        setlocal EnableDelayedExpansion
        echo(!line:%search%=%content%!
        endlocal
    )
)

endlocal
pause

正如您所看到的,可以使用切换延迟扩展,但您必须考虑到endlocal以外的任何变量都会丢失(除非您建立一些对策)。

  1. 让我们首先关注第二个for /F循环结构:

    set "textfile=index.html"
    set "newfile=index-active.html"
    > "%newfile%" (
        for /F "usebackq delims=" %%i in ("%textfile%") do (
            set "line=%%i"
            setlocal EnableDelayedExpansion
            echo(!line:%search%=%content%!
            endlocal
        )
    )
    

    在你做的事情中切换延迟扩张已经很好了。它可以避免感叹号的丢失;在扩展%%i时,如果禁用延迟扩展,一切都很好;在扩展%%i时,如果启用延迟扩展,感叹号会丢失(或导致其他意外结果),因为延迟扩展功能会消耗此感叹号;对于普通环境变量扩展行%var%也是如此。

    setlocal之后,您不需要设置变量line,您可以立即回显被操纵的字符串;但即使您重新分配line,也没有问题,因为line未在endlocal后面使用,它是在下一次循环迭代中新分配的。

  2. 现在让我们关注第一个for /F循环结构:

    set "content="
    for /F "usebackq delims=" %%x in ("%replace%") do (
       set "item=%%x"
       setlocal EnableDelayedExpansion
       for /F "delims=" %%a in ("content=!content!!item!") do (
           endlocal
           set "%%a"
       )
    )
    setlocal EnableDelayedExpansion
    echo(!content!
    endlocal
    

    我们再次希望通过切换延迟扩展来避免感叹号丢失。但是,这在这里很棘手,因为您需要将变量content传递给下一个循环迭代。因此,首先将%%x分配给临时变量item,同时禁用延迟扩展;然后在启用延迟扩展时完成连接,但是变量content的重新分配被延迟到endlocal之后的稍后时间点,使用仅迭代一次的for /F循环并且返回%%a中的整个赋值表达式,该表达式在set之后传递给endlocal命令。由于在循环结构完成后禁用了延迟扩展,因此需要重新启用它以再次回显content;当然,像echo(%content%这样的正常扩展也可以起作用,但如果content包含一些特殊字符,它可能会失败,所以应该避免使用。

  3. 最后,整个脚本以setlocal命令开头,所有选项都明确指定,并以endlocal命令结束,因此批处理脚本不依赖于调用的设置{ {1}}实例并且不会影响其环境。