在循环和递归中替换字符串会产生意想不到的副作用



我试图创建一个程序,我通过文件(在一个文件夹和它的所有子文件夹),并动态地替换一行的其他部分。为了做到这一点,我编写了一个程序,但发现它的行为出乎意料。

不只是字符串被替换,而是整行被替换。然后我做了一些实验,看到在循环之外,字符串替换的行为与预期一样,但在.......内部陌生的开始。

下面是一个非常基本的例子,在循环中使用普通的字符串替换。

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

循环之外的所有替换都像我认为的那样工作。但是在循环内部,看起来集合在echo完成之前就已经完成了。因为我认为这和我的行替换问题有相同的来源/原因,我的问题是:为什么程序产生这个意外的输出?我怎么做才能得到期望的输出呢?

编辑:在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..
    )

echo %test%第一次出现在"before",第二次出现在"after"

Short:在解析时,在执行块之前完成百分比展开。

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

因此存在延迟展开,这是在执行单个命令时计算的。
语法几乎相同,但使用感叹号代替百分号。
但是在使用延迟展开之前,必须使用

来启用它。
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!
    )

最新更新