BAT file: the contents of the variable as part of another variable

Suppose I have a variable a with the contents of " 123 " and a variable b123 with some text in it. For some reason, I want to use the variable a as part of the var middle name. Something like that:

SET a=123 SET b123=some_text_in_it rem i want next line to output "some_text_in_it" echo %b%a%% 

so I want to combine the text with the contents of var and use the resulting string as the variable name to echo this content. The sample above does not work, and I understand why I probably need to add some kind of group. How to do this, preferably in one line?

+4
source share
3 answers

There are two common ways for this CALL or DelayedExpansion

 setlocal EnableDelayedExpansion SET a=123 SET b123=some_text_in_it rem i want next line to output "some_text_in_it" call echo %%b%a%%% echo !b%a%! 

CALL uses the fact that the call will re-process the line a second time, the first time it will expand only %a% , and double %% will be reduced to one %
call echo %b123%
And in the second step, %b123% will be expanded.
But the CALL technique is slow and not very safe, so DelayedExpansion should be preferred.

DelayedExpansion works because exclamation points expand at a later phase of the parser than percent decomposition.
And that is also the reason why delayed expansion is much safer.

Edit: method for arrays containing numbers
If you work with arrays that contain only numbers, you can also use set /a to access them.
This is much simpler than the FOR or CALL technique, and it also works in blocks.

 setlocal EnableDelayedExpansion set arr[1]=17 set arr[2]=35 set arr[3]=77 ( set idx=2 set /a val=arr[!idx!] echo !var! ) 
+8
source

The best reason to "use a variable as part of the var middle name" is to access array elements (vector and matrix) through an index variable. Although this is exactly the same as in the example above, it looks much clearer:

 setlocal EnableDelayedExpansion set i=123 set v[123]=Value of element 123 call echo %%v[%i%]%% echo !v[%i%]! 

Although CALL slower than Delayed Expansion , as mentioned above, it can be nested several times, which allows you to use the second (or deeper) direction to access the elements of the array. This function can be used in complex data structures such as linked lists. For instance:

 set i=123 set v[123]=456 set w[456]=Value of element 456 call call echo %%%%w[%%v[%i%]%%]%%%% 

EDIT . For some reason, I don’t understand, the Delayed Expansion version of the last command does not work correctly:

 call echo !w[%%v[%i%]%%]! 
+2
source

There is another way to accomplish a task that is very useful if both variables were assigned within the same block in brackets, which extends them. The solution is similar to jeb's delayed expand response, except that the FOR variable is used instead of the usual extension.

 @echo off setlocal enableDelayedExpansion :: Define a linefeed value - only needed for last variant set LF=^ :: The two blank lines above are critical to the definition of LF ( set A=123 set B123=some_text_in_it rem ECHO !B%A%! will fail because A was assigned within the same block rem This works as long as A does not contain * or ? for %%A in ("!A!") do echo !B%%~A! rem This works as long as A does not start with EOL character (; by default) for /f "delims=" %%A in ("!A!") do echo !B%%A! rem This will never fail because it disables EOL by setting it to a linefeed for /f eol^=^%LF%%LF%^ delims^= %%A in ("!A!") do echo !B%%A! ) 

You can also use the CALL trick, but it is relatively slow and relatively unreliable - see CALL , or it is better to avoid calling .

The definition and use of the linefeed variable is discussed in Explain how the hack variable works for the new version.

Setting EOL for line feed is described in detail in HOW: FOR / F Disabling EOL or using a quote as delim . Using an LF variable instead of embedding strings in a FOR statement is simply an extension of the method. This makes the code more readable.

EDIT
An easier way to safely use the FOR method for any valid value is to set the EOL sign to an equal sign, since no user-defined variable can contain name = in the name.

 for /f "eol== delims=" %%A in ("!A!") do echo !B%%A! 
+2
source

Source: https://habr.com/ru/post/1401339/


All Articles