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)
这意味着:"每次替换str1
在variable
用str2
".
你的情况都str1
和str2
是参数,而不是文字字符串.直接使用上面的模板,您最终可能会得到以下表达式:
%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!
;
命令即将执行 - !
表达式被计算(x
s被s替换y
);
执行命令 - output
修改变量.
现在关于警告.要记住的第一件事是它!
成为语法的一部分,并在遇到时被消费和解释.因此,您需要在想要将其用作文字(例如^!
)的地方进行转义.
另一个警告是SETLOCAL/ENDLOCAL块的主要影响.问题是,这样一个区域内环境变量的所有变化都是本地的.退出块时(执行时ENDLOCAL
),变量设置为输入之前的值(执行前SETLOCAL
).这对您来说意味着更改后的值output
仅在SETLOCAL
您必须首先使用延迟扩展启动的块中有效.可能这在您的特定情况下可能不是问题,如果您只需要修改该值然后立即使用它,但您可能必须记住它以备将来使用.
注意:根据jeb的注释,您可以保存修改后的值并使用此技巧保留SETLOCAL块:
ENDLOCAL & SET "output=%output%"
Run Code Online (Sandbox Code Playgroud)
的&
操作者只需限定的命令时,他们被放置在同一直线上.它们按照指定的顺序依次执行.问题是,在解析该行的那一刻,尚未留下SETLOCAL块,因此%output%
评估修改后的值仍然有效.但是,分配实际执行后 ENDLOCAL
,即离开块之后.因此,您在离开块后有效地存储修改后的值,从而保留更改.(谢谢,杰布!)
更多信息:
关于延迟扩张:
关于子串替换: