循环中的字符串替换和具有意外副作用的递归

时间:2015-10-07 06:25:12

标签: batch-file replace windows-7

我正在尝试创建一个程序,我在其中浏览文件(在文件夹及其所有子文件夹中),并动态地用其他部分替换部分行。为此,我制作了一个程序,但发现它表现得出乎意料。

而不仅仅是被替换的字符串,WHOLE行被替换了。然后我做了一些实验,看到在循环之外,字符串替换表现得如预期,但内部.......奇怪的开始。

下面是一个非常基本的例子,在循环中有一个正常的字符串替换。

@echo off   
call :Rekursiv
goto :eof

:Rekursiv
    set str=teh cat in teh hat
    echo "Outside"
    echo %str%
    set str=%str:teh=the%
    echo %str%  
    echo "Outside end"

    for /D %%d in (*) do (
            cd %%~fd

            set str=teh cat in teh hat
            echo %str%
            set str=%str:teh=the%
            echo %str%      

            call :Rekursiv      

            cd..
    )

    exit /b     

现在通常我会指望:

teh cat in teh hat
the cat in the hat

和一些外部和外部散布在中间,但我得到的是:

"Outside"
teh cat in teh hat        <--- as expected
the cat in the hat        <--- as expected
"Outside end"
the cat in the hat        <--- Completely unexpected as its the replaced string already!
the cat in the hat
"Outside"
teh cat in teh hat
the cat in the hat
"Outside end"
the cat in the hat
the cat in the hat
"Outside"
teh cat in teh hat
the cat in the hat
"Outside end"
the cat in the hat
the cat in the hat
"Outside"
teh cat in teh hat
the cat in the hat
"Outside end"

循环外的所有替换都按照我认为应该的方式工作。但是在循环内部看起来这些集合都是在回声完成之前完成的。我认为这和我的线路替换问题有相同的来源/因为我的问题在这里:为什么程序产生这种意外的输出?我该怎么做才能获得预期的输出?

编辑:在MCDN评论之后,我尝试了一些事情:

@echo off   
call :Rekursiv
goto :eof

:Rekursiv
    set str=teh cat in teh hat
    echo "Outside"
    echo %str%
    set str=%str:teh=the%
    echo %str%  
    echo "Outside end"


set "test=before"
if defined test (
    set "test=after"
    echo %test%
)   

    for /D %%d in (*) do (
            cd %%~fd

            set str=teh cat in teh hat
            echo %str%
            set str=%str:teh=the%
            echo %str%      

set "test=before"
if defined test (
    set "test=after"
    echo %test%
)

            call :Rekursiv      

            cd..
    )

第一次出现&#34; echo%test%&#34;是&#34;之前&#34;第二个是&#34;在&#34;

之后

1 个答案:

答案 0 :(得分:0)

简短:在解析时执行块之前完成扩展百分比。

在内部执行任何操作之前,您可以看到具有固定字符串的块。

因此存在延迟扩展,这在执行单个命令时进行评估 语法几乎相同,但使用感叹号代替百分号 但在使用延迟扩展之前,必须使用

启用
setlocal EnableDelayedExpansion

所以你的代码看起来像

@echo off   
setlocal EnableDelayedExpansion
call :Rekursiv
goto :eof

:Rekursiv
    set str=teh cat in teh hat
    echo "Outside"
    echo %str%
    set str=%str:teh=the%
    echo %str%  
    echo "Outside end"

    for /D %%d in (*) do (
            cd %%~fd

            set "str=teh cat in teh hat"
            echo !str!
            set str=!str:teh=the!
            echo !str!
    )