Windows Batch Programming: Evaluating Indirect / Nested Variables

We have a text file with a list of bunches and a batch file that reads lines from this file.

For example, TargetFolders.txt may contain the line:

%ProgramFiles%\Acme\FooBar %VersionNumber% 

Naturally, when we read this line from a text file (using the FOR command), the %% variable I get the actual text of the line with% characters, and does not replace the values ​​of the variables. Thus,

 SET VersionNumber=7.0 FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO ( echo Folder: %%I ) 

Print

 Folder: %ProgramFiles%\Acme\FooBar %VersionNumber% 

How to get him to replace the actual values ​​of variables so that he prints

 Folder: C:\Program Files\Acme\FooBar 7.0 

?

+4
source share
3 answers
 SET VersionNumber=7.0 FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO ( for /F "usebackq delims=" %%J in (`echo %%I`) do echo Folder: %%J ) 

There you go. (This is what you wanted, right?)

+7
source

Just adding CALL may solve your problem. (also invalid VersionNumber definition)

 SET VersionNumber=7.0 FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO ( call echo Folder: %%I ) 

But this will fail if your file contains unquoted special characters such as & , > , < , | .

For example, the following line will not be executed:

 %ProgramFiles%\This&That\ %VersionNumber% 

It will work if specified

 "%ProgramFiles%\This&That\" %VersionNumber% 

CALL will also cripple any quotation marks: "^" will become "^^"

The best solution would be to change your text file and replace every % with ! .

 !ProgramFiles!\Acme\FooBar !VersionNumber! !ProgramFiles!\This&That !VersionNumber! 

Now you can safely use the delayed extension to expand the variables inside the loop.

 setlocal enableDelayedExpansion SET VersionNumber=7.0 FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO ( echo Folder: %%I ) 

If your text file already has ! which you want to save, it must be escaped. Also ^ must be escaped if it appears on line with ! .

 preserve caret ^^ and exclamation ^! by escaping caret ^ without exclamation is no problem 

Alternatively, you can replace variables for carriage and exclamation letters

 alternate method to preserve caret !c! and exclamation !x! caret ^ without exclamation still no problem 

And then define the variables in your batch

 setlocal enableDelayedExpansion set "x=^!" set "c=^" SET VersionNumber=7.0 FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO ( echo Folder: %%I ) 
+5
source

In addition to existing helpful answers with a more robust option that also correctly handles the following inline characters: & | < > ^ & | < > ^ [1]

Note that for simplicity, I use a string to control the outer loop, whose literal value, which should be expanded later in the inner loop, is %ProgramFiles%\Acme\FooBar %VersionNumber% due to double instances of % .

 set "VersionNumber=0.7" for /f "delims=" %%f in ("%%ProgramFiles%%\Acme\FooBar %%VersionNumber%%") do ( for /f "delims=" %%g in ('echo "%%f"') do echo Folder: [%%~g] ) 

This gives something like Folder: [C:\Program Files\Acme\FooBar 0.7]

Note:

  • By default, for /f interprets a single-quoted string ( '...' ) as the command to execute and whose output to capture; delims= tells for to capture the output as a whole in one variable.
    (Although you can use usebackq with the `...` -included command instead, there is no advantage to this in this case.)
  • Note that the reference to the outer loop variable has double quotes ( "%%f" ), which allows this value to contain the specified special characters without breaking the echo command.

  • Since the output will also be double, the ~ operator ~ used to separate closed double quotes from the captured value during echo repetition ( %%~g ).


[1] A solution that additionally processes embedded " instances is more complex:

  rem Construct a variable whose value contains all shell metacharacters. rem % chars. meant to be treated as literals must be doubled (%%) rem Note the extra " at the end, which appends an unbalanced double quote. set "var=%%OS%% & %%ba^r | (baz) <mo'>"" rem Embedded " chars. must be escaped as "" (doubling them). for /f "delims=" %%v in ('echo "%var:"=""%"') do set "expandedVar=%%~v" rem Note: The resulting variable value: rem - can only be echoed *double-quoted*, as the command will otherwise break. rem - still contains the *doubled* embedded double quotes, which, however, rem is the escaping that other Microsoft programs expect. echo "[%expandedVar%]" 

This gives: "[Windows_NT & %ba^r | (baz) <mo'>""]"

0
source

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


All Articles