Windows 批处理中的字符串替换

bee*_*ear 3 windows batch find-and-replace string

我试图了解 Windows 批处理中的字符串替换实际上是如何工作的并且遇到了问题。

@echo off
set var=wild
set varnew=%var:l=n%
echo var is: %var%
echo varnew is: %varnew%
Run Code Online (Sandbox Code Playgroud)

确实有效;它生成预期的输出:

var is: wild
varnew is: wind
Run Code Online (Sandbox Code Playgroud)

但这不是(示例目录“Main”):

@echo off
for /D %%G IN (*) do (
    setlocal
    echo G is: %%G
    set _srcp=%%G
    echo _srcp is %_srcp%
    rem set _newp=%_newp:ai=_01_% <-- confused variable
    set _newp=%_srcp:ai=_01_%
    echo._newp is: %_newp%
    endlocal
                     )
Run Code Online (Sandbox Code Playgroud)

它生成此输出:

G is: Main
_srcp is Main
_newp is: %_srcp:ai=_01_
Run Code Online (Sandbox Code Playgroud)

我希望代码生_newp is: M_01_n成为最后一行。我在这里真的没有想法,有人可以指出我正确的方向吗?

BB

dbe*_*ham 5

你有几个问题:

  • %var%在解析语句时会发生扩展,并且在执行任何命令之前,一次解析整个括号内的代码块。所以该值是循环开始之前存在的值。解决方案是延迟扩展,它发生在循环中的每个命令正在执行时。

  • 你的逻辑是错误的 - _newp 的分配应该基于 _srcp 的值

CMD 处理器是一个复杂的野兽(而且文档也很差)。各种类型的变量的扩展点有很多,如果你真的想充分利用批处理编程,你必须充分理解它们。链接里都有说明,但总结一下,展开的顺序是:

1) % expand - Parameter: echo %1 or Environment variable: echo %var%
---- 大多数解析现在已经完成 ----
2) FOR 变量扩展: for %%A in (*) do echo %%A
3) Delayed environment variable expand: echo !var!
4) CALL % expand - Parameter: call echo %%1 or Environment variable: call echo %%var%%
5) SET /A 环境变量扩展:`set /a "value=var+1"

请注意,延迟扩展需要通过以下方式启用延迟扩展 SETLOCAL EnableDelayedExpansion

以下使用延迟扩展的代码将给出您寻求的结果:

@echo off
for /D %%G in (*) do (
  setlocal enableDelayedExpansion
  echo G is: %%G
  set "_srcp=%%G"
  echo _srcp is !_srcp!
  set "_newp=!_srcp:ai=_01_!"
  echo _newp is: !_newp!
  endlocal
)
Run Code Online (Sandbox Code Playgroud)

请注意,延迟扩展FOR变量扩展之后发生,所以,结果将如果被损坏%%Gconstains !。这可以通过额外的 SETLOCAL 来避免:

for /D %%G in (*) do (
  setlocal disableDelayedExpansion
  echo G is: %%G
  set "_srcp=%%G"
  setlocal enableDelayedExpansion
  echo _srcp is !_srcp!
  set "_newp=!_srcp:ai=_01_!"
  echo _newp is: !_newp!
  endlocal
  endlocal
)
Run Code Online (Sandbox Code Playgroud)

您也可以使用带有双百分比的 CALL 获得所需的结果,但这要慢得多。如果执行几次,速度并不重要,但如果在一个循环中执行数千次,则速度变得非常重要。

@echo off
for /D %%G in (*) do (
  setlocal
  echo G is: %%G
  set "_srcp=%%G"
  call echo _srcp is %%_srcp%%
  call set "_newp=%%_srcp:ai=_01_%%"
  call echo _newp is: %%_newp%%
  endlocal
)
Run Code Online (Sandbox Code Playgroud)