【问题标题】:How to replace string inside a bat file with command line parameter string如何用命令行参数字符串替换bat文件中的字符串
【发布时间】:2011-08-14 13:01:56
【问题描述】:

我在一个 cmd 批处理文件中有以下内容:

for /f %%l in (%2) do (for %%f in (%%l) do copy "%%f" %1))

注意:这个脚本基本上是读取一个包含分号分隔的 txt 文件的文本文件,该文件的路径由 %2 给出(例如,其中包含 c:\test1\file1.cs;d:\file2.js)并复制文件到 %1 指定的目标文件夹。

我需要将%1 参数的字符串值x(也传递给批处理文件,例如%3)替换为%4 值,该值也作为参数传递给批处理文件。

例如:

if %1 = 'test replace x with y'
%3=x
%4=y

所以输出应该是'test replace y with y'

如何使用 Windows CMD 批处理解释器实现此目的?

【问题讨论】:

  • 很难解析你的请求。为什么不能在需要的时候都使用 %4 而忽略 %3? ......向我们展示更多关于您拥有的东西的详细信息,我们应该能够提供帮助。祝你好运。
  • @shelter,问题是 %3 和 %4 不同,此批处理由外部 MSBuild 脚本调用。替换字符串和要替换的字符串是不同的,例如:我可能需要用“y”替换 FIND STRING 中出现的“x”(例如“test replace x x x)”谢谢....

标签: windows scripting command-line batch-file


【解决方案1】:

首先,您必须将%1 存储到一个变量中,然后您才能执行替换。

基本上,替换的语法是这样的:

%<i>variable</i>:<i>str1</i>=<i>str2</i>%

这意味着:'将variable 中的每个str1 替换为str2'

在您的情况下,str1str2 都是参数,而不是文字字符串。直接使用上面的模板,你可能会得到这个表达式:

%variable:%3=%4%.

但这会使解析器感到困惑,因为它不知道应该首先评估%3%4。事实上,它会首先尝试评估%variable:%(并失败)。

在这种情况下,一种解决方案可能是使用一种称为'lazy'延迟评估的方法。基本上,您将评估变量的命令传递给 CALL 命令。原始命令到它的“CALL 版本”的转换是这样的:

ECHO %var% ==> CALL ECHO %%var%%.

注意双重%s。在解析时,它们被评估为单个 %s。生成的命令将由 CALL 再次解析,最终效果与原始命令的情况相同,ECHO %var%

所以它的工作原理与原始命令相同(这很好),我们在这里获得的是评估的后期时间,我的意思是最终评估,当变量实际被替换时以其价值。了解了这种效果,我们可以构造表达式,首先计算 %3%4,然后计算整个结果表达式。具体来说,像这样:

%%variable:%3=%4%%

第一次解析后,这个表达式会变成这样:

%variable:x=y%

这将被再次解析,输出将是 variable 修改后的内容。

为了更好地说明,这里有一个简单的工作示例:

SET "output=%1"
CALL SET output=%%output:%3=%4%%
ECHO %output%

更新

还有另一种方法可以做同样的事情,我可能应该先提到它。

Windows 命令外壳支持正确 延迟扩展。它使用起来更简单,但有一些注意事项。

首先,如何使用它。延迟扩展的语法是!var!,而不是立即扩展的%var%(它仍然有效,可以与延迟扩展语法一起使用)。

在您使用以下命令启用语法之前,!var! 可能无法在您的脚本中运行:

SETLOCAL EnableDelayedExpansion

ENDLOCAL 命令关闭延迟扩展语法在其中有效并由命令 shell 解释的块。

上面的示例脚本可以这样重写:

SET "output=%1"
SETLOCAL EnableDelayedExpansion
SET output=!output:%3=%4!
ECHO !output!
ENDLOCAL

那么在SET output=!output:%3=%4! 命令的情况下这是如何工作的:

  • %3%4 被立即评估,即在解析时——它们分别被 xy 替换;

  • 命令变成这样:SET output=!output:x=y!;

  • 命令即将执行 - 评估 ! 表达式(xs 替换为 ys);

  • 命令被执行——output 变量被修改。

现在关于注意事项。首先要记住的是! 成为语法的一部分,并在遇到时被使用和解释。所以你需要在你想用它作为文字的地方转义它(比如^!)。

另一个警告是 SETLOCAL/ENDLOCAL 块的主要影响。问题是,在这样一个块中对环境变量的所有更改都是本地的。在退出块时(在执行ENDLOCAL 时),变量被设置为进入它之前的值(在执行SETLOCAL 之前)。这对您来说意味着 output 的更改值将仅在 SETLOCAL 块内有效,您必须首先启动该块以使用延迟扩展。如果您只需要修改该值然后立即使用它,在您的特定情况下这可能不是问题,但您可能必须记住它以备将来使用。

注意:根据 jeb 的评论,您可以使用此技巧保存修改后的值并离开 SETLOCAL 块:

ENDLOCAL & SET "output=%output%"

&amp; 运算符只是将命令放在同一行时对其进行分隔。它们按照指定的顺序一个接一个地执行。问题是,在解析行的那一刻,SETLOCAL 块还没有离开,所以%output% 评估为修改后的值,它仍然有效。但是赋值实际上是在之后 ENDLOCAL 执行的,即在离开块之后。因此,您在离开块后有效地存储了修改后的值,从而保留了更改。 (谢谢,jeb!)


更多信息:

  1. 关于延迟扩展:
  1. 关于子串替换:

【讨论】:

  • +1,但是为什么你显示“惰性”延迟评估,而不是(更简单的)延迟扩展?
  • @jeb:感谢您的提问!出于某种原因,不知道为什么,当我进行测试时(在 Win7 上)这对我不起作用:set "output=%1"; setlocal EnableDelayedExpansion; set "output=!output:%3=%4!"; endlocal; echo %output%。奇怪的是,!output:%3=%4! 在 ECHO 中工作,但拒绝对 SET 产生任何影响。变量不会改变。
  • 但这没关系,当您更改setlocal 块中的输出变量时,在endlocal 之后,输出变量具有它的原始值。不是Win7的问题
  • 您可以通过( endlocal &amp; set "output=%output%")离开块并保存修改后的值
  • @dgo:这很好奇。我刚刚在 Win 7 中测试了您的第一种方法,seemed to work as expected 为我(屏幕截图中的ECHO test--test 行是脚本中的ECHO %var2%)。也许我错过或误解了什么。
【解决方案2】:

我在 Windows 7 批处理文件中尝试了以下代码:

SET output=%1
CALL SET output=%output:unsigned=signed%
CALL SET output=%output:.apk=-aligned.apk%

有效!

【讨论】:

  • 但这并不能解决问题。问题是关于用 %3%4 中的 unknown 参数替换字符串
【解决方案3】:

如果您需要在一个字符串中替换多个参数,只需使用“for /f”来设置具有先前替换的变量,如下所示:

SET "output1=%1"
CALL SET output1=%%output1:%3=%4%%
for /f "tokens=1" %%a in ('echo %output1%') do set output2=%%a
CALL SET output2=%%output2:%5%6%
for /f "tokens=1" %%a in ('echo %output2') do set output3=%%a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 2023-04-11
    • 2020-09-02
    相关资源
    最近更新 更多