具有意外副作用的循环和递归中的字符串替换
String replacement in loops and recursions with unexpected side effects
我正在尝试创建一个程序,我可以在其中浏览文件(在一个文件夹及其所有子文件夹中)并用其他部分动态替换一行的一部分。为此,我编写了一个程序,但发现它的行为异常。
不仅替换了字符串,还替换了整行。然后我做了一些实验,发现在循环之外,字符串替换的行为符合预期,但在内部......奇怪开始了。
下面是一个非常基本的示例,在循环中进行了正常的字符串替换。
@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"
循环外的所有替换都按我认为的那样工作。但在循环内部,似乎在回声完成之前所有集合都已完成。因为我认为这和我的换行问题有相同的问题 source/cause 我的问题是:为什么程序会产生这个意外的输出?我该怎么做才能获得预期的输出?
编辑:在 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"
简短:在执行块之前完成百分比扩展,同时进行解析。
在里面执行任何东西之前,你可以看到带有固定字符串的块。
因此存在延迟扩展,这是在执行单个命令时评估的。
语法几乎相同,但使用的是感叹号而不是百分号。
但在您可以使用延迟扩展之前,必须启用
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!
)
我正在尝试创建一个程序,我可以在其中浏览文件(在一个文件夹及其所有子文件夹中)并用其他部分动态替换一行的一部分。为此,我编写了一个程序,但发现它的行为异常。
不仅替换了字符串,还替换了整行。然后我做了一些实验,发现在循环之外,字符串替换的行为符合预期,但在内部......奇怪开始了。
下面是一个非常基本的示例,在循环中进行了正常的字符串替换。
@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"
循环外的所有替换都按我认为的那样工作。但在循环内部,似乎在回声完成之前所有集合都已完成。因为我认为这和我的换行问题有相同的问题 source/cause 我的问题是:为什么程序会产生这个意外的输出?我该怎么做才能获得预期的输出?
编辑:在 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"
简短:在执行块之前完成百分比扩展,同时进行解析。
在里面执行任何东西之前,你可以看到带有固定字符串的块。
因此存在延迟扩展,这是在执行单个命令时评估的。
语法几乎相同,但使用的是感叹号而不是百分号。
但在您可以使用延迟扩展之前,必须启用
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!
)