How to use Windows console 'set' variables

2020-04-22 23:37发布

问题:

This works in Windows console as expected:

set A="qwerty" && echo %A%

the output: "qwerty"

But when I try to run the same commands in NPM scipts:

package.json:

"scripts": {
  "qwerty": "set A=\"qwerty\" && echo %A%"
}

> npm run qwerty

the output is: %A%

Am I doing something wrong or it just shouldn't work that way when run by NPM?

回答1:

Your example set A="qwerty" && echo %A% isn't correct. Variables in the cmd prompt / a batch file are expanded once per line / command:

==> set "A="

==> echo %A%
%A%

==> set A="qwerty" && echo %A%
%A%

==> echo %A%
"qwerty"

Why this behaviour?

The SET command was first introduced with MS-DOS 2.0 in March 1983, at that time memory and CPU were very limited and the expansion of variables once per line was enough.

A workaround using the CALL command:

==> set "A="

==> echo %A%
%A%

==> set A="qwerty" && CALL echo %A%
"qwerty"

Edit:

For the sake of completeness, the following batch script shows the mechanism of percent expansion and its combination with the CALL command in detail (note doubled % percent signs in the batch file CALL Echo %%_var%%):

@ECHO OFF
SETLOCAL
if NOT "%~1"=="" ECHO ON
echo        1st:
Set "_var=first"
Set "_var=second" & Echo %_var% & CALL Echo %%_var%%  
echo        2nd: 
Set "_var=first"
Set "_var=second" & CALL Echo %%_var%% & Echo %_var%  

Output, echo OFF:

==> D:\bat\SO\55237418.bat
       1st:
first
second
       2nd:
second
first

Output, echo ON:

==> D:\bat\SO\55237418.bat on

==> echo        1st:
       1st:

==> Set "_var=first"

==> Set "_var=second"   & Echo first   & CALL Echo %_var%
first
second

==> echo        2nd:
       2nd:

==> Set "_var=first"

==> Set "_var=second"   & CALL Echo %_var%   & Echo first
second
first


回答2:

What I found so far is that these commands in order to work properly must be in different scripts and run in a specific order. So, here is the way how it works:

"scripts": {
  "aaa": "set TMP=test && npm run bbb",
  "bbb": "echo %TMP%"
}

npm run aaa

output: test

But this one wouldn't work:

"scripts": {
  "aaa": "set TMP=test",
  "bbb": "npm run aaa && echo %TMP%"
}

npm run bbb

output: <just empty>

It looks like two separate npm run commands are required to find the created variable: the variable should be created in the first npm run and could be found in the second one.