如何使用命令行参数字符串替换bat文件中的字符串

时间:2011-04-28 09:03:48

标签: windows scripting command-line batch-file

我在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

所以输出应该'测试用y'替换y

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

3 个答案:

答案 0 :(得分:49)

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

基本上,替换的语法是:

%variable:str1=str2%

表示:'用str1'替换variable中的每个str2

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

%variable:%3=%4%

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

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

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

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

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

%%variable:%3=%4%%

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

%variable:x=y%

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

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

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

<强>更新

还有另一种做同样事情的方法,我应该先提一下。

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

首先,如何使用它。延迟扩展的语法为!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!;

  • 该命令即将执行 - !表达式已被评估(xy s替换;

  • 执行命令 - 修改output变量。

现在关于警告。要记住的第一件事是!成为语法的一部分,并在遇到时被消费和解释。所以你需要在它想要用作文字的地方(例如^!)将其转义。

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

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

ENDLOCAL & SET "output=%output%"

&运算符只需将命令放在同一行上即可。它们按照指定的顺序依次执行。问题是,在解析该行的那一刻,还没有留下SETLOCAL块,因此%output%计算修改后的值,该值仍然有效。但是,分配实际上是在 ENDLOCAL之后执行的,即在离开块之后。因此,您在离开块后有效地存储修改后的值,从而保留更改。 (谢谢, jeb !)


更多信息:

  1. 关于延迟扩张:

  2. 关于子串替换:

答案 1 :(得分:1)

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

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

有效!

答案 2 :(得分:-1)

如果你需要在一个字符串中替换几个参数,只需使用“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