106} How to test whether a variable is a non-negative integer?
This is one of the items which arose from a solution I needed
myself. Test for a decimal (10-base) non-negative integer. The
original solution is given after the simpler one below:
@echo off & setlocal enableextensions
if "%~1"=="" (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Do a regular expression (/r) findstr complement
echo %s%|findstr /r "[^0-9]">nul
if %errorlevel% GTR 0 (set isInteger=true) else (set isInteger=false)
::
:: Show the result
echo %s%
echo isInteger=%isInteger%
::
endlocal & goto :EOF
Examples of output
C:\_D\TEST>cmdfaq 1234
1234
isInteger=true
or
C:\_D\TEST>cmdfaq FF
FF
isInteger=false
or
C:\_D\TEST>cmdfaq 2x
2x
isInteger=false
Actually, a non-negative integer!
More fully
@echo off & setlocal enableextensions
if "%~1"=="" (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Do a regular expression (/r) findstr complement and avoid the octal trap
echo %s%|findstr /r "[^0-9]">nul||set isDecInteger=true
if defined isDecInteger if not "%s:~1,2%"=="" if "%s:~0,1%"=="0" set IsDecInteger=
::
:: Show the result
if defined IsDecInteger (
echo %s% is a regular, non-negative integer
) else (
echo %s% is not a regular, non-negative integer
)
::
endlocal & goto :EOF
Another findstr formulation (for the first code option) to avoid the
octal trap:
echo %s%|findstr /b /e /v /r "0 [1-9][0-9]*">nul
Originaly, I had
@echo off & setlocal enableextensions enabledelayedexpansion
if "%~1"=="" (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Get its length, counting from zero
set charCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1)
set /a charCount=%charCount%-1
::
:: Test that only valid characters are present
set isInteger=true
for /l %%c in (0,1,%charCount%) do (
set si=!s:~%%c,1!
echo 1234567890|findstr /l "!si!">nul
if !errorlevel! GTR 0 set isInteger=false
)
::
:: Show the result
echo %s%
echo isInteger=%isInteger%
::
endlocal & goto :EOF
Examples of output
C:\_D\TEST>cmdfaq 1234
1234
isInteger=true
or
C:\_D\TEST>cmdfaq FF
FF
isInteger=false
The solution can be expanded to other numeric or alphabetic validity
tests. For example to test if a variable is a positive decimal
number.
@echo off & setlocal enableextensions enabledelayedexpansion
if "%~1"=="" (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Get its length, counting from zero
set charCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1)
set /a charCount=%charCount%-1
::
:: Test that only valid characters are present
set isNumeric=true
set pointCount=0
for /l %%c in (0,1,%charCount%) do (
set si=!s:~%%c,1!
echo 1234567890.|findstr /l "!si!">nul
if !errorlevel! GTR 0 set isNumeric=false
if [!si!]==[.] set /a pointCount+=1
)
if %pointCount% GTR 1 set isNumeric=false
::
:: Show the result
echo %s%
echo isNumeric=%isNumeric%
::
endlocal & goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq 12.34
12.34
isNumeric=true
or
C:\_D\TEST>cmdfaq 1..
1..
isNumeric=false
Or, more concisely
@echo off & setlocal enableextensions enabledelayedexpansion
if "%~1"=="" (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Test if non-valid characters are present
set isNumeric=true
echo %s%|findstr "[^0-9.]">nul
if %errorlevel% EQU 0 set isNumeric=false
::
:: Count the decimal points in the variable s
set pointCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if [!si!]==[.] set /a pointCount+=1
)
if %pointCount% GTR 1 set isNumeric=false
::
:: Show the result
echo %s%
echo isNumeric=%isNumeric%
::
endlocal & goto :EOF
Another example. The parameter to be given is a time parameter in
the HH:MM format. Test for its validity.
@echo off & setlocal enableextensions enabledelayedexpansion
if "%~1"=="" (
echo Usage: %~f0 TimeParameterHH:MM
goto :EOF)
::
:: Test for the time parameter validity
:: Get the parameter into a variable
set s=%~1
::
:: Get its length and count the number of colons
set charCount=0
set pointCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1
if [!si!]==[:] set /a pointCount+=1
)
::
:: Test that only valid characters are present
set isNumeric=true
echo %s%|findstr "[^0-9:]">nul
if %errorlevel% EQU 0 set isNumeric=false
::
:: Test for the right composition
if %pointCount% GTR 1 set isNumeric=false
if %charCount% GTR 5 set isNumeric=false
::
:: Get the components
for /f "tokens=1,2 delims=:" %%a in ("%s%") do (
set shour=%%a
set sminute=%%b)
if not defined sminute set sminute=0
::
:: Test that the time is within bounds
if %shour% GTR 23 set isNumeric=false
if %sminute% GTR 59 set isNumeric=false
::
:: Show the result
echo s=%s%
echo shour=%shour%
echo sminute=%sminute%
echo isNumeric=%isNumeric%
::
endlocal & goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq 13:58
s=13:58
shour=13
sminute=58
isNumeric=true
or
C:\_D\TEST>cmdfaq 25:11
s=25:11
shour=25
sminute=11
isNumeric=false