【问题标题】:String replacement in loops and recursions with unexpected side effects具有意外副作用的循环和递归中的字符串替换
【发布时间】:2015-10-07 06:25:12
【问题描述】:

我正在尝试创建一个程序,在其中遍历文件(在文件夹及其所有子文件夹中)并用其他部分动态替换行的一部分。为此,我编写了一个程序,但发现它的行为异常。

整个行被替换,而不是仅仅替换字符串。然后我做了一些实验,发现在循环之外,字符串替换的行为符合预期,但在内部......奇怪开始了。

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

@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..
    )

“echo %test%”的第一次出现是“之前”,第二次是“之后”

【问题讨论】:

  • 也许this 可以提供帮助
  • @MCND 嗯嗯有趣的一点。在循环之外我明白了。但是在循环内部它是“之后”你知道为什么在那里吗? (“之前”我希望它在循环外是相同的,但我在循环内得到了之后)。时刻将在那里更新解决方案。
  • 啊,也许我明白了。是否可以这样:第一次出现在此之前,尽管 if 设置生效,因此第二次回声因此设置为之后? (因为它在查看之前的“test=before”之前解析了第二个 %test%?)

标签: batch-file replace windows-7


【解决方案1】:

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

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

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

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!
    )

【讨论】:

    猜你喜欢
    • 2012-04-18
    • 2013-02-01
    • 2017-04-24
    • 2011-05-09
    • 2021-05-03
    • 2021-04-02
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    相关资源
    最近更新 更多