如何用命令行参数字符串替换bat文件中的字符串 [英] How to replace string inside a bat file with command line parameter string

查看:26
本文介绍了如何用命令行参数字符串替换bat文件中的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have following in a cmd batch file:

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

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

note : this script basically does is read a text file that contains semicolon delimited txt file whose path is given by %2(eg which contains c: est1file1.cs;d:file2.js) and copy the files to destination folder specified by %1.

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

I need to replace the %1 parameter's string value of x (which is also passed to batch file e.g. %3) with %4 value which is also passed as parameter to batch file.

例如:

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

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

so the output should be 'test replace y with y'

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

How can I achieve this using Windows CMD batch interpreter?

推荐答案

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

First of all, you'll have to store %1 into a variable, then you will be able to perform the replacements.

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

Basically, the syntax for the replacement is this:

%variable:str1=str2%

这意味着:'用str2'替换variable中的每个str1.

which means: 'replace every str1 in variable with str2'.

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

In your case both str1 and str2 are parameters, not literal strings. Using the above template directly you might end up with this expression:

%variable:%3=%4%.

但这会混淆解析器,因为它不知道应该首先评估 %3%4.事实上,它会首先尝试评估 %variable:%(并失败).

But that would confuse the parser, as it wouldn't know that %3 and %4 should be evaluated first. In fact, it would first try to evaluate %variable:% (and fail).

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

One of the solutions in this case could be to use a method called 'lazy' delayed evaluation. Basically, you are passing the command where you are evaluating a variable, to the CALL command. The transformation of the original command to its 'CALL version' is like so:

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

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

Note the double %s. At parse time they are evaluated to single %s. The resulting command would be parsed again by CALL, and the ultimate effect would be the same as in case of the original command, ECHO %var%.

所以它和原来的命令一样(这很好),我们在这里得到的是求值的后期,我的意思是最后的求值,当变量实际被替换时以其价值.知道了这种影响,我们可以以这样一种方式构造我们的表达式:首先评估 %3%4,然后是整个结果表达式.具体来说,像这样:

So it works the same as the original command (which is good), and what we are gaining here is the later time of evaluation, I mean the final evaluation, when the variable is actually replaced with its value. Knowing about that effect, we can construct our expression in such a way that %3 and %4 are evaluated first, and then the entire resulting expression. Specifically, like this:

%%variable:%3=%4%%

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

After the first parse this expression would become something like this:

%variable:x=y%

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

That would be parsed again, and the output would be variable's modified contents.

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

For better illustration, here's a simple working example:

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


更新

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

There's another method of doing the same thing, which I should probably have mentioned first.

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

The Windows command shell supports a proper delayed expansion. It is simpler in use, but has some caveats.

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

First, how to use it. The syntax for delayed expansion is !var! instead of %var% for immediate expansion (which remains valid and can be used alongside with the delayed expansion syntax).

可能 !var! 在您使用以下命令启用语法之前不会在您的脚本中工作:

Probably !var! will not work in your script until you enable the syntax with the command:

SETLOCAL EnableDelayedExpansion

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

The ENDLOCAL command closes the block within which the delayed expansion syntax is valid and interpreted by the command shell.

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

The above example script could be rewritten like this:

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

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

So how this works in case of the SET output=!output:%3=%4! command:

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

  • %3 and %4 are evaluated immediately, i.e. at the parse time – they are replaced with x and y respectively;

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

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

the command is about to execute – the ! expression is evaluated (xs are replaced with ys);

命令被执行——output变量被修改.

the command is executed – the output variable is modified.

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

Now about the caveats. The first thing to remember is that the ! becomes part of the syntax and is consumed and interpreted whenever encountered. So you'll need to escape it where you want to use it as a literal (like ^!).

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

Another caveat is the primary effect of a SETLOCAL/ENDLOCAL block. The thing is, all the changes to environment variables within such a block are, well, local. Upon exiting the block (upon executing ENDLOCAL) the variable is set to the value it had prior to entering it (prior to executing SETLOCAL). This means for you that the changed value of output will only be valid within the SETLOCAL block which you had to initiate for using the delayed expansion in the first place. Possibly this may not be a problem in your particular case, if you just need to modify the value and then use it right away, but you should probably have to remember it for the future.

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

Note: As per jeb's comment, you can save the modified value and leave the SETLOCAL block using this trick:

ENDLOCAL & SET "output=%output%"

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

The & operator simply delimits the commands when they are placed on the same line. They are executed one after the other, in the same order they are specified. The thing is, by the moment of parsing the line, the SETLOCAL block hasn't been left yet, so %output% evaluates to the modified value, which is still valid. But the assignment is actually executed after ENDLOCAL, i.e. after leaving the block. So you are effectively storing the modified value after leaving the block, thus preserving the changes. (Thanks, jeb!)

更多信息:

  1. 关于延迟扩张:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆