Batch Scripting Help - Replace Substring of a Dela

2019-02-24 02:43发布

问题:

Basically I'm trying to do !var1:SomeText=!var2!! but this code doesn't work. What am I missing?

回答1:

The order of expansion is critical when doing a search and replace operation that uses a variable for the search and/or the replace. The inner variable must be expanded before the outer search and replace expansion takes place. Trying to used delayed expansion for both obviously can't work because the delayed expansion occurs at one point in time.

The classic method for expansion of a variable within another variable uses delayed expansion for the outer, and normal for the inner: echo !var1:SomeText=%var2%!"

I am going to assume you wanted to use delayed expansion for both for a reason. Perhaps the expansion occurs within a block of code and one of the variables was set in the same block. Normal expansion won't work because it can't see the value that was assigned within the block until after the block concludes.

Solution 1

One way to solve the problem is to use CALL:

call echo %%var1:SomeText=!var2!%% 

This works as follows:

  1. The percent phase of the parser converts double percents into single percents, resulting in
    call echo %var1:SomeText=!var2!%

  2. The delayed expansion expands !var2!, resulting in
    call echo %var1:SomeText=ReplacementText%

  3. The CALL ECHO is executed and an additional level of percent processing takes place. The search and replace expansion is executed, resulting in ResultOfSearchAndReplace being echoed to the screen.

This works, but it is relatively slow. It also can have problems if the expanded value has special characters like >, & or |. I rarely use this technique.

Solution 2

The fast and more reliable method is to do the expansion in two steps. First transfer the value of !var2! to a FOR variable. You can then use the FOR variable as the replacement string and use delayed expansion for the second step. This completely avoids the more brittle percent expansion.

for /f "delims=" %%A in ("!var2!") do echo !var1:SomeText=%%A!

The above works because FOR variable expansion takes place before delayed expansion.

This is by far my preferred method to attack this problem.

For a more thorough explanation of the various phases of the batch parser, refer to jeb's answer to How does the Windows Command Interpreter (CMD.EXE) parse scripts?