如何替换Windows批处理文件中的变量内容

时间:2010-12-06 14:18:32

标签: windows batch-file cmd

我正在编写一个简单的脚本,用其他文本替换环境变量中的文本。我得到的麻烦是从其他变量拉出替换或替换文本

SET a=The fat cat
ECHO %a%
REM Results in 'The fat cat'
ECHO %a:fat=thin%
REM Results in 'The thin cat'

工作正常(输出是'肥猫'和'瘦猫'

但是,如果'fat'或'thin'在变量中,它就不起作用

SET b=fat
ECHO %a:%c%=thin%
REM _Should_ give 'The thin cat'.
REM _Actually_ gives '%a:fat=thin%' (the %c% is evaluated, but no further).

REM using delayed evaluation doesn't make any difference either
ECHO !a:%c%=thin!
REM Actual output is now '!a:fat=thin!'

我知道这可以像以前在博客中看到的那样完成,但我从未保存过博客的链接。

有人有什么想法吗?

PS。我在Windows 7上运行脚本

PPS。我知道这在Perl / Python /其他脚本语言中更容易选择,但我只是想知道为什么那些应该很容易的事情并不是很明显。

PPPS。我也尝试过明确启用延迟扩展的脚本

SETLOCAL enabledelayedexpansion

这没什么区别。

7 个答案:

答案 0 :(得分:12)

请尝试以下方法:

将代码复制并粘贴到记事本中,并将其另存为批处理文件。

   @echo off
   setlocal enabledelayedexpansion

   set str=The fat cat
   set f=fat

   echo.
   echo          f = [%f%]

   echo.
   echo        str = [%str%]

   set str=!str:%f%=thin!

   echo str:f=thin = [%str%]

我希望你确信!

答案 1 :(得分:8)

使用来电。将以下内容放在批处理脚本中并运行它:

set a=The fat cat
set b=fat
set c=thin

REM To replace "%b%" with "%c%" in "%a%", we can do:
call set a=%%a:%b%^=%c%%%
echo %a%
pause

如上所述here,我们使用以下事实:

  

CALL internal_cmd

     

...

     

internal_cmd 运行内部命令,首先展开参数中的所有变量

在我们的案例中, internal_cmd 最初设置a = %% a:%b%^ =%c %%%

扩展后 internal_cmd 变为设置a =%a:胖=瘦%

因此,在我们的案例中运行

  

调用设置a = %% a:%b%^ =%c %%%

等效到正在运行:

  

设置a =%a:fat = thin%

答案 2 :(得分:2)

问题:

echo %a:%c%=thin%

是它尝试扩展两个变量:a:=thin,它们之间带有c常量字符串。

试试这个:

echo echo ^%a:%c%=thin^% | cmd

第一个命令输出:

echo %a:fat=thin%

通过管道输入第二个命令shell进行评估。

答案 3 :(得分:2)

而且......这个怎么样?

@echo off
setlocal enabledelayedexpansion

set str=The fat cat
set f=fat
set t=thin

echo.
echo       f = [%f%]
echo       t = [%t%]

echo.
echo     str = [%str%]

set str=!str:%f%=%t%!

echo str:f=t = [%str%]

Nifty嗯?

答案 4 :(得分:1)

最近我遇到了同样的情况。如前所述,我在下面使用过并且工作过......

set filearg=C:\data\dev\log\process
set env=C:\data\dev

REM I wanted \log\process as output

SETLOCAL enabledelayedexpansion
set str2=!filearg:%env%=!
echo Output : %str2%
echo.
endlocal

输出:

\log\process

它有效.. !!

答案 5 :(得分:0)

我尽量避免使用SETLOCAL enabledelayedexpansion ... ENDLOCAL所有(或几乎所有)时间,因为通常我想设置或修改一些变量,我希望新值在脚本的其他区域或之后可用批处理脚本结束(SETLOCAL | ENDLOCAL将忘记脚本中的任何新变量或对变量的更改。有时这很方便,但对我来说,我发现它'通常不是。

目前我使用 @Zuzel 描述的方法,但在我了解该方法之前,我曾经使用过这个,这非常相似(但看起来有点复杂):

for /F "usebackq delims=" %%f in (`echo set "a=^%a:%b%=%c%^%"`) do @%%f

示例脚本:

@echo off

set a=The fat cat
set b=fat
set c=thin

@echo.
@echo before: "%a%"

@echo replace "%b%" with "%c%" in "%a%" using for:
for /F "usebackq delims=" %%f in (`echo set "a=%%a:%b%=%c%%%"`) do @%%f
@echo after for:  "%a%"

goto :EOF

运行脚本的输出:

before: "The fat cat"
replace "fat" with "thin" in "The fat cat" using for:
after for:  "The thin cat"

我喜欢这种方法,因为您可以使用修改后的变量调用外部程序(或内部命令),并捕获和处理命令的输出(逐行)。

但是,对于大多数情况,Zuzel的方法更简单,更清洁,包括你描述的那种情况。

注意:

这两种方法(当然还有SETLOCAL enabledelayedexpansion ... ENDLOCAL)只有在批处理脚本中运行时才能正常工作。如果您尝试在命令提示符窗口中直接使用这两种方法中的任何一种("调用"或"用于"),您将获得与从脚本运行输出的内容不同的内容

例如,将其作为脚本运行:

@echo off

set a=The fat cat
set b=fat
set c=thin
set d=calico
set e=sleepy

@echo.
@echo before: "%a%"
@echo.

@echo replace "%b%" with "%c%" in "%a%" using call:
call set a=%%a:%b%=%c%%%
@echo after call: "%a%" ("%b%" to "%c%")

@echo.
@echo replace "%c%" with "%d%" in "%a%" using for:
for /F "usebackq delims=" %%f in (`echo set "a=%%a:%c%=%d%%%"`) do @%%f
@echo after for:  "%a%" ("%c%" to "%d%")

@echo.
@echo replace "%d%" with "%e%" in "%a%" using call:
call set a=%%a:%d%=%e%%%
@echo after call: "%a%" ("%d%" to "%e%")

运行脚本的输出:

before: "The fat cat"

replace "fat" with "thin" in "The fat cat" using call:
after call: "The thin cat" ("fat" to "thin")

replace "thin" with "calico" in "The thin cat" using for:
after for:  "The calico cat" ("thin" to "calico")

replace "calico" with "sleepy" in "The calico cat" using call:
after call: "The sleepy cat" ("calico" to "sleepy")

现在,直接在命令提示符窗口中运行这些命令:

c:\>
c:\>set a=The fat cat

c:\>set b=fat

c:\>set c=thin

c:\>set d=calico

c:\>set e=sleepy

c:\>
c:\>@echo.


c:\>@echo before: "%a%"
before: "The fat cat"

c:\>@echo.


c:\>
c:\>@echo replace "%b%" with "%c%" in "%a%" using call:
replace "fat" with "thin" in "The fat cat" using call:

c:\>call set a=%%a:%b%=%c%%%

c:\>@echo after call: "%a%" ("%b%" to "%c%")
after call: "%The thin cat%" ("fat" to "thin")

c:\>
c:\>@echo.


c:\>@echo replace "%c%" with "%d%" in "%a%" using for:
replace "thin" with "calico" in "%The thin cat%" using for:

c:\>for /F "usebackq delims=" %f in (`echo set "a=%%a:%c%=%d%%%"`) do @%f

c:\>@echo after for:  "%a%" ("%c%" to "%d%")
after for:  "%%The calico cat%%" ("thin" to "calico")

c:\>
c:\>@echo.


c:\>@echo replace "%d%" with "%e%" in "%a%" using call:
replace "calico" with "sleepy" in "%%The calico cat%%" using call:

c:\>call set a=%%a:%d%=%e%%%

c:\>@echo after call: "%a%" ("%d%" to "%e%")
after call: "%%%The sleepy cat%%%" ("calico" to "sleepy")

c:\>

从命令提示符窗口检查输出行的前后行:

before: "The fat cat"

replace "fat" with "thin" in "The fat cat" using call:
after call: "%The thin cat%" ("fat" to "thin")

replace "thin" with "calico" in "%The thin cat%" using for:
after for:  "%%The calico cat%%" ("thin" to "calico")

replace "calico" with "sleepy" in "%%The calico cat%%" using call:
after call: "%%%The sleepy cat%%%" ("calico" to "sleepy")

请注意,替换是正确的,但也注意到直接在命令提示符窗口中运行这些命令,它会添加一组"%"每次进行替换时,在预期值之前和之后(百分号)。因此,很难直接在命令提示符窗口中测试这些方法。

答案 6 :(得分:0)

::在%var%= ~s / $ old / $ new /

上使用perl
set var=The fat cat
set old=fat
set new=thin

ECHO before=%var%

for /f "delims=" %%m in ('echo %var% ^|perl -pe "s/%old%/%new%/" ') do set var=%%m

ECHO after=%var% 

输出:

before=The fat cat
after=The thin cat