我正在编写一个简单的脚本,用其他文本替换环境变量中的文本。我得到的麻烦是从其他变量拉出替换或替换文本
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
这没什么区别。
答案 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 /
上使用perlset 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