1) Default values
undefined variables are more or less empty variables, but only inside batch files.
The difference for batch files and command line
Code: Select all
echo var: %undefinedVar%
Output when executed on the command line:
var: %undefinedVar%
Output when executed in a batch file
var:
Sometimes it would be usefull to has a replacement or default value for undefined variables, this can be done with a simple construct
Code: Select all
echo var: %undefinedVar:myDefaultValue%=%
Output:
var: myDefaultValue
2) Forcing Errors with text
While playing with macros, I got sometimes unexpected errors, like "The command resultLen is unknown ...".
Then I searched for the cause and found a line like
Code: Select all
%$strlen% resultLen myString
To catch problems like this, I could add lines like
Code: Select all
if not defined $strLen echo ERROR: Macro is not defined
Code: Select all
%$strlen:(#)ERROR_Macro_is_undefefined---%=% resultLen myString
Code: Select all
"ERROR_Macro_is_undefefined---" kann syntaktisch an dieser Stelle nicht verarbeitet werden.
But this technic has some limits.
- The error text can't contain percent signs nor equal signs.
- The text can't contain raw delimiters like "<space>;,=", they have to be escaped
- It only works for macros, because the (#) construct only creates a syntax error when it parsed like a command
It fails, if it isn't used as a command, it simply output the text
Code: Select all
echo %myVariable:(#)ERROR_Macro_is_undefefined---%=%
...
Outut:
(#)ERROR_Macro_is_undefefined---
Code: Select all
echo %myVariable:-%~*------- ERROR: macro is undefefined ------=%
Output:
Die folgende Verwendung des Pfadoperators zur Ersetzung eines Batchparameters
ist ungültig: %~*------- ERROR: macro is undefefined ------=%
Geben Sie CALL /? oder FOR /? ein, um herauszufinden, welche Formate gültig
sind.
2b) Loading macro when not defined
I'm using 2) also for my LOAD_ONCE macro
Code: Select all
%$LIB_LOAD_ONCE:call "%~dp0\libBase.cmd" "%~f0" :=%
The $LIB_LOAD_ONCE macro itself allows a batch file to execute commands only once, even when the same batch file is called later again (In my case it happens when libraries include other libraries)
Code: Select all
:define_$LIB_LOAD_ONCE
rem %$MACRO_PREPARE% $LIB_LOAD_ONCE
(set \n=^^^
)
if "%LIBRARY_DEBUG%" GTR "0" (
set "_LIBRARY_DEBUG1.tmp=call echo Load library %%~n0, ready it's already loaded"
set "_LIBRARY_DEBUG2.tmp=call echo Load library %%~n0"
)
REM *** In debug mode, show the loading of libBase
%_LIBRARY_DEBUG2.tmp%
REM *** This wraps the exclamation mark, works independent if delayed expansion is enabled or disabled
FOR /F %%! in ("! ! ^^^!") DO ^
set ^"$LIB_LOAD_ONCE=(%\n%
setlocal EnableDelayedExpansion %\n%
set "path="%\n%
set "pathExt=;"%\n%
call set "libVarname=$%%~n0.loaded" %\n%
FOR /F "delims=" %%^^L in ("%%!libVarname%%!") DO ( %\n%
endlocal %\n%
if defined %%~^^L ( %\n%
%= library is already loaded =% %\n%
%_LIBRARY_DEBUG1.tmp% %\n%
exit /b %\n%
) else ( %\n%
set "%%~L=1" %\n%
%= library needs to be loaded =% %\n%
%_LIBRARY_DEBUG2.tmp% %\n%
) %\n%
) %\n%
) "
exit /b
Sometimes you want to echo , set a variable or define a macro with exclamation marks, but you don't know the state of delayed expansion.
That's a problem, because normally the definitions are different.
Code: Select all
setlocal DisableDelayedExpansion
set "var1=Containg two exlamation marks, one normal ! and one quoted "!""
echo Two exlamation marks, one normal ! and one quoted "!"
setlocal EnableDelayedExpansion
set "var2=Containg two exlamation marks, one normal ^! and one quoted "^^!""
echo Two exlamation marks, one normal ^^! and one quoted "^!"
set var
Code: Select all
setlocal DisableDelayedExpansion
call :test
setlocal EnableDelayedExpansion
call :test
exit /b
:test
FOR /F %%! in ("! ! ^^^!") DO (
set "var=Containing two exlamation marks, one normal %%! and one quoted "%%!""
echo Two exlamation marks, one normal %%! and one quoted "%%!"
set var
)
exit /b
But when delayed expansion is enabled, then the string is expanded to simply "^!" and that goes into the %%! parameter.
And in the echo/set command, the %%! expansion occours after the sepcial character phase but before the delayed expansion phase.
Therefore the "^!" results into a single "!", that's all.
3b) Exclamation marks and disappearing quotes
A small extension to 3)
Sometimes you want to echo variables containing closing parenthesis, like in "C:\Program Files (x86)", but it fails inside code blocks.
I could be solved by enclosing the expression into quotes, but then the quotes are also visible.
Or you use quotes that disappears!
Code: Select all
setlocal DisableDelayedExpansion
call :test
setlocal EnableDelayedExpansion
call :test
exit /b
:test
FOR /F "tokens=1,2 " %%! in ("#") DO FOR /F %%! in ("! ! ^^^!") DO (
echo %%"Show &|<> and C:\Program Files (x86) without quotes %%!
)
exit /b
The inner loop overlays the definition of %%! to "!" or "^!".
Using %%" works like a quote, it escapes all characters in the special character phase, but later it expands to nothing
4) Conditional FOR parameter
Sometimes (okay, normally you want this only when defining macros) you would like content in a FOR parameter depending on a variable.
Code: Select all
@echo off
set "DEBUG="
call :test
set "DEBUG=no it's defined"
call :test
exit /b
:test
FOR /F "tokens=1,2" %%5 in ("X %DEBUG%") DO ^
FOR /F "tokens=2-4" %%5 in ("%%~6 "^;" "" "^;"") DO ^
FOR /F "delims=" %%5 in (^"^
%%~5"Text in case of UNDEFINED "^
%= Empty line, used to create a line feed =%
%%~6"Text in case when DEBUG is DEFINED, can even contain: %~f0""
) DO (
echo %%~5
)
exit /b
Code: Select all
Text in case of UNDEFINED
Text in case when DEBUG is DEFINED, can even contain: c:\temp\t5.bat