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

DSh*_*per 13 windows scripting command-line batch-file

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

for /f %%l in (%2) do (for %%f in (%%l) do copy "%%f" %1))
Run Code Online (Sandbox Code Playgroud)

注意:此脚本基本上是读取包含分号分隔的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
Run Code Online (Sandbox Code Playgroud)

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

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

And*_*y M 50

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

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

%variable:str1=str2%
Run Code Online (Sandbox Code Playgroud)

这意味着:"每次替换str1variablestr2".

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

%variable:%3=%4%.

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

在这种情况下,解决方案之一可能是使用一种称为"懒惰"延迟评估的方法.基本上,您将要评估变量的命令传递给CALL命令.将原始命令转换为"CALL版本"是这样的:

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

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

所以它的工作方式与原始命令相同(这很好),我们在这里得到的是评估的后期,我的意思是最终的评估,当变量实际上被其值替换时.了解关于这个效果,我们可以构建我们表达这样一种方式,%3并且%4首先评估,然后将整个结果表达式.具体来说,像这样:

%%variable:%3=%4%%
Run Code Online (Sandbox Code Playgroud)

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

%variable:x=y%
Run Code Online (Sandbox Code Playgroud)

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

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

SET "output=%1"
CALL SET output=%%output:%3=%4%%
ECHO %output%
Run Code Online (Sandbox Code Playgroud)

UPDATE

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

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

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

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

SETLOCAL EnableDelayedExpansion
Run Code Online (Sandbox Code Playgroud)

ENDLOCAL命令将关闭延迟扩展语法有效并由命令shell解释的块.

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

SET "output=%1"
SETLOCAL EnableDelayedExpansion
SET output=!output:%3=%4!
ECHO !output!
ENDLOCAL
Run Code Online (Sandbox Code Playgroud)

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

  • %3%4立即评估,即在解析时 - 分别用x和替换y;

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

  • 命令即将执行 - !表达式被计算(xs被s替换y);

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

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

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

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

ENDLOCAL & SET "output=%output%"
Run Code Online (Sandbox Code Playgroud)

&操作者只需限定的命令时,他们被放置在同一直线上.它们按照指定的顺序依次执行.问题是,在解析该行的那一刻,尚未留下SETLOCAL块,因此%output%评估修改后的值仍然有效.但是,分配实际执行 ENDLOCAL,即离开块之后.因此,您在离开块后有效地存储修改后的值,从而保留更改.(谢谢,杰布!)


更多信息:

  1. 关于延迟扩张:

  2. 关于子串替换: