在for循环内查找并替换 [批处理脚本]

6
下面的代码有效,输出test.test
set replaceWith=.
set str="test\test"
call set str=%%str:\=%replaceWith%%%
echo %str%

然而,下面的代码echo ggg.hhhhh所有4次

SET SERVICE_LIST=(aaa\bbb ccc\dddd eeee\fffff ggg\hhhhh)

for %%i in %SERVICE_LIST% do (
set replaceWith=.
set str="%%i"
call set str=%%str:\=%replaceWith%%%
echo %str%
)

我在这里做错了什么?
2个回答

7
请准备一本关于Windows命令行脚本语言的教材,然后尝试以下内容:
@ECHO OFF &SETLOCAL
SET "SERVICE_LIST=(aaa\bbb ccc\dddd eeee\fffff ggg\hhhhh)"

for /f "delims=" %%i in ("%SERVICE_LIST%") do (
    set "replaceWith=."
    set "str=%%i"
    SETLOCAL ENABLEDELAYEDEXPANSION
    call set "str=%%str:\=!replaceWith!%%"
    echo !str!
    ENDLOCAL
)

7
如果你理解为什么你的代码使用了call set str=%%str:\=%replaceWith%%%,那么你应该能够理解这个问题;-)
%var%这样的语法在解析行时会被扩展,并且整个带括号的FOR循环将在一次解析中解析。因此,在进入循环之前存在的值将用于%replaceWith%echo %str%
CALL语句对于每次迭代都要经过额外的解析层级,但这只部分解决了问题。
第一次运行脚本时,你可能只得到了4次“ECHO is on.”(或关闭)。然而,脚本完成后,str的值可能是ggghhhhhreplaceWith.。由于没有SETLOCAL,所以当你再次运行时,这些值现在在循环开始之前就已经设置好了。第二次运行后,你可能会得到4次ggghhhhh。从那时起,每次运行脚本时,你都会得到4次ggg.hhhhh
你可以通过在ECHO语句中使用CALL并将replaceWith的赋值移到循环之前来获得所需的结果。
@echo off
setlocal
SET SERVICE_LIST=(aaa\bbb ccc\dddd eeee\fffff ggg\hhhhh)
set "replaceWith=."
for %%i in %SERVICE_LIST% do (
  set str="%%i"
  call set str=%%str:\=%replaceWith%%%
  call echo %%str%%
)

但是有一种更好的方法-延迟扩展。
@echo off
setlocal enableDelayedExpansion
SET "SERVICE_LIST=aaa\bbb ccc\dddd eeee\fffff ggg\hhhhh"
set "replaceWith=."
for %%i in (%SERVICE_LIST%) do (
  set str="%%i"
  set str=!str:\=%replaceWith%!
  echo !str!
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接