What restrictions are there on batch file variable names, and why?
I noticed that I am not able to echo a variable with the name :)
.
h:\uprof>set :)=123
h:\uprof>set :)
:)=123
h:\uprof>echo %:)%
%:)%
From a batch file obviously :)
is outputted instead of %:)%
. The problem is clearly not with the set
command, as the variable, and it's value, are appearing in the output of set
.
Strangely, when separated - :
or )
- and reversed - ):
- all output their given values when used as variable names.
The only character that cannot ever appear in a user defined batch environment variable name is =
. The SET statement will terminate a variable name at the first occurrence of =
, and everything after will be part of the value.
It is simple to assign a variable name containing a :
, but the value cannot normally be expanded except under specific circumstances.
When extensions are enabled (default behavior)
The colon is part of search/replace and substring expansion syntax, which interferes with expansion of variables containing colon in the name.
There is one exception - if the :
appears as the last character in the name, then the variable can be expanded just fine, but then you cannot do search and replace or substring expansion operations on the value.
When extensions are disabled
Search/replace and substring expansion are not available, so there is nothing to stop expansion of variables containing colons from working just fine.
@echo off
setlocal enableExtensions
set "test:=[value of test:]"
set "test:more=[value of test:more]"
set "test"
echo(
echo With extensions enabled
echo -------------------------
echo %%test:%% = %test:%
echo %%test::test=replace%% = %test::test=replace%
echo %%test::~0,4%% = %test::~0,4%
echo %%test:more%% = %test:more%
setlocal disableExtensions
echo(
echo With extensions disabled
echo -------------------------
echo %%test:%% = %test:%
echo %%test:more%% = %test:more%
--OUTPUT--
test:=[value of test:]
test:more=[value of test:more]
With extensions enabled
-------------------------
%test:% = [value of test:]
%test::test=replace% = :test=replace
%test::~0,4% = :~0,4
%test:more% = more
With extensions disabled
-------------------------
%test:% = [value of test:]
%test:more% = [value of test:more]
See https://stackoverflow.com/a/7970912/1012053 for a complete description of exactly how variable expansion works.
:
is the string manipulation special character for variable expansion. Example:
%var:~0,1%
Therefore, if anything follows :
in the variable name, it will try to perform string manipulation and fail. This allows for the :
colon character by itself or when nothing trails it.
Rule Regarding Expanding Variable Names: Variable names must not contain :
followed by any characters otherwise, the variable expansion will fail.
See set /?
set :)=123
set a)=123
set :a=123
set :=123
set )=123
echo %:)%
echo %a)%
echo %:a%
echo %:%
echo %)%
Output:
%:)%
123
%:a%
123
123
There are few other things to look out for.
If you have a variable with a name that starts with a digit, for example set "1var=foo"
, that would make batch script parser think it's dealing with an argument %1
instead of variable %1var%
, and even if no argument was passed, it will still expand into an empty string resulting in var%
. Likewise, if you start variable with ~
parser will expect an argument terminated by digit, like %~dp0
. If you won't terminate it with a digit, however (set "~dp=bar"
), it won't be possible to access it with %~dp%
, as that will result in a error:
The following usage of the path operator in batch-parameter substitution is invalid: %~dp%
It's still possible to access such variables via delayed expansion (!1var!
, !~dp!
) but to keep things clear it's best to avoid starting variable names with digit or tilde in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With