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

发布于 2024-10-06 03:14:09 字数 795 浏览 0 评论 0原文

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

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

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

但是,如果“胖”或“瘦”在变量中,则不会 我知道

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

这没有什么区别。

I'm writing a simple script to substitute text in an environment variable with other text. The trouble I get is with the substituted or substituted text being pulled from other variables

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

Works fine (output is 'The fat cat' and 'The thin cat'

However, if 'fat' or 'thin' are in variables, it doesn't work

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

I know this can be done as I've seen it in blogs before, but I never saved the link to the blogs.

Anyone have any ideas?

PS. I'm running the scripts on Windows 7

PPS. I know this is easier in Perl/Python/other script language of choice, but I just want to know why something that should be easy is not immediately obvious.

PPPS. I've also tried the scripts with delayed expansion explicitly turned on

SETLOCAL enabledelayedexpansion

This makes no difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

沧桑㈠ 2024-10-13 03:14:09

请尝试以下操作:

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

   @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%]

我希望你能被说服!

Please try the following:

Copy and paste the code into Notepad and save it as a batch file.

   @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%]

I hope you're convinced!

柏拉图鍀咏恒 2024-10-13 03:14:09

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

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

此处所述,我们使用以下事实:

调用internal_cmd

...

internal_cmd运行内部命令,首先扩展参数中的任何变量

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

扩展后internal_cmd变为set a=%a:fat=thin%

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

调用集a=%%a:%b%^=%c%%%

相当于运行:

设置a=%a:fat=thin%

Use CALL. Put the following in a batch script and run it:

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

As stated here, we use the fact that:

CALL internal_cmd

...

internal_cmd Run an internal command, first expanding any variables in the argument.

In our case internal_cmd is initially set a=%%a:%b%^=%c%%%.

After expansion internal_cmd becomes set a=%a:fat=thin%.

Thus, in our case running

call set a=%%a:%b%^=%c%%%

is equivalent to running:

set a=%a:fat=thin%.

妖妓 2024-10-13 03:14:09

: 的问题

echo %a:%c%=thin%

在于它尝试扩展两个变量:a:=thin,并在它们之间使用 c 常量字符串。

试试这个:

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

第一个命令输出:

echo %a:fat=thin%

它将通过管道传输到第二个命令 shell 中进行评估。

The problem with:

echo %a:%c%=thin%

is that it tries to expand two variables: a: and =thin with a c constant string between them.

Try this:

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

The first command outputs:

echo %a:fat=thin%

which is piped into a second command shell for evaluation.

坏尐絯℡ 2024-10-13 03:14:09

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

目前我使用@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 的方法对于大多数情况(包括您的情况)来说更简单、更清晰。描述的。

注意:

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

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

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

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

I try to avoid using SETLOCAL enabledelayedexpansion ... ENDLOCAL all (or nearly all) the time, because usually I want to set or modify a few variables and I want the new values to be available in other areas of the script or after the batch script ends (SETLOCAL|ENDLOCAL will forget about any new variables or changes to variables in the "SETLOCAL" part of the script. Sometimes that's handy, but for me I find it's usually not.

Currently I use the method described by @Zuzel, but before I knew about that method, I used to use this, which is very similar (but looks a bit more complicated):

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

example script:

@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

the output from running the script:

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

I like this method because you can call external programs (or internal commands) using modified variables and also capture and process the output of the command (line by line).

But, Zuzel's method is simpler and cleaner for most situations, including the one you described.

Note:

Both of these methods (and also SETLOCAL enabledelayedexpansion ... ENDLOCAL, of course), only work correctly if run from within a batch script. If you try to use either of these two methods ("call" or "for") directly in a command prompt window, you will get something different from what the output was running from a script.

For example, run this as a script:

@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%")

the output from running the script:

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

Now, run those commands directly in a command prompt window:

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:\>

examine the before and after output lines from the command prompt window:

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

Notice that the substitutions are made correctly, but also notice that with running these commands directly in the command prompt window, it adds a set of "%" (percent signs) before and after the expected value each time the substitution is made. So, it makes it difficult to test any of these methods directly in the command prompt window.

獨角戲 2024-10-13 03:14:09

还有……这个怎么样?

@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%]

漂亮吧?

And... How about this?

@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 eh?

要走干脆点 2024-10-13 03:14:09

最近我遇到了同样的情况..如前所述,我使用了如下所示的方法并工作了...

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

它工作了..!!

Recently I came accross the same situation..As said earlier, I used like below and worked...

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

Output :

\log\process

It worked..!!

少年亿悲伤 2024-10-13 03:14:09

:: 在 %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

:: Use perl on %var% =~ s/$old/$new/

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% 

Output:

before=The fat cat
after=The thin cat
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文