mhshams
mhshams

Reputation: 16952

How to check if a parameter (or variable) is a number in a Batch script

I need to check if a parameter that is passed to a Windows Batch file is a numeric value or not. It would be good for the check to also works for variables.

I found an answer to a similar question, where the findstr command is used with a regular expression.

I did try that solution, but it’s not working like I hoped (at least on Windows 7).

My test scenarios are as follows:

AA  # not a valid number
A1  # not a valid number
1A  # not a valid number

11  # a valid number

Upvotes: 27

Views: 80309

Answers (11)

Sven
Sven

Reputation: 1

I know that this is a quite old thread, but I ran into that problem, too. Some of the proposals given up to this point can (for example) not handle a "&" entered. And I wanted to have a "one-line" solution (no CALL etc.) that is "rock solid" regarding this kind of "poison" characters entered as (part of) keyboard input. My proposal takes a "whitelist"/"cinderella"-approach, checks the variable in question (varinput) digit by digit, simply picks out the "good" ones and concatenates them to "varcleaned".

set varcleaned=&& FOR /L %%i IN (0,1,10) DO (FOR %%j IN (A B C D 0 1 2 3 4) DO (IF "!varinput:~%%i,1!" EQU "%%j" (SET varcleaned=!varcleaned!%%j)))

I have tested it against the most common "poison" characters - and it works. In the example given the whitelist is A to D and 0 to 4 and there are 11 rounds (meaning it does its job for varinput < 12 digits). So, if you would like to have "a numeric" value as varcleaned, simply change the whitelist accordingly. Once you have "cleaned" the variable, you could proceed with the other solutions mentioned above like set /a varinput = %varcleaned% 2>nul. For performance reasons I would keep the number of walkthroughs and the whitelist as small as possible.

Upvotes: 0

npocmaka
npocmaka

Reputation: 57252

if errorlevel accepts only numeric values which can be used for a checks:

set test_var=001
( 
  (if errorlevel %test_var% break ) 2>nul
)&&(
  echo %test_var% is numeric
)||(
  echo %test_var% is NOT numeric
)

set test_var=001X
( 
  (if errorlevel %test_var% break ) 2>nul
)&&(
  echo %test_var% is numeric
)||(
  echo %test_var% is NOT numeric
)

the first check will pass, the second not. Though the script above would not handle unary + - if you want to handle this case too check - isInteger.bat

Upvotes: 1

user3347790
user3347790

Reputation: 133

I use a more low tech approach. It only works with integers and supports negative values.

set "XVALUE=%~1"
set /A XVALUE=XVALUE
if "%XVALUE%" NEQ "%~1" goto :invalid_value

The first line gets the command line argument and drops it into XVALUE. Using the "quotes" prevents issues with various special characters.

The second line looks mysterious but takes advantage of that when there is a text string on the right hand side of the equals sign for SET /A that it's interpreted as an environment variable containing a numeric value. The command processor parses the presumed numeric value without generating any error messages nor setting ERRORLEVEL. Doing it this way always results in XVALUE being converted into a valid numeric value regardless of whatever was passed to us.

The third line is optional and is only needed if you want to be strict about that the argument is a numeric value in the range -2147483648 to 2147483647. If you don't use the if test then

  • You get support for octal and hexadecimal numbers by prefixing them with 0 or 0x.
  • If someone uses a very small or large number such as -9999999999999 or 9999999999999 then XVALUE will be set to the minimum or maximum allowed values which are -2147483648 and 2147483647.
  • If someone uses garbage such as the word "hello" then XVALUE is set to 0. If it's something like 123x456 then the parser stops at the "x" and XVALUE is set to 123.

Upvotes: 1

Alim &#214;zdemir
Alim &#214;zdemir

Reputation: 2624

The easiest for positive integers should be:

IF 1%1 NEQ +1%1 echo Notnumeric!

If negative numbers (hyphen) are also to be considered, this will work

SET number=%1
if 1%1 EQU +1%1 echo positive number
if %1==-%number:-=% echo negative number

Learned from this article here

Upvotes: 12

Celes
Celes

Reputation: 37

Just try to divide per 1. But it doesn't work with numbers out of Z (non relative integer or decimal).

set var=29
set /a number=%var% >nul 2>&1
set /a number=%number% / 1 >nul 2>&1
if "%var%" == "%number%" (echo numeric) else (echo NOT numeric)

Upvotes: 2

Arvo Bowen
Arvo Bowen

Reputation: 4929

I use this function instead, it seems to work for me without any issues...

The Script (mytestscript.bat)

REM == Script variables =============================================
SET "NUMCODE=%1"
SET "NAME=%2"

REM == Main script ==================================================
CALL :Validate "NUMCODE"
IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%
CALL :Validate "NAME"
IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%

ECHO Validation Complete and all variables passed validation.

REM == Functions ====================================================
:IsNumeric [string-value] [return-val]
    SET "stringVal=%~1"
    SET /A numericVal=%stringVal% > nul 2> nul
    IF "%stringVal%"=="%numericVal%" (SET "%~2=1") ELSE (SET "%~2=0")
    EXIT /B 0

:Validate
    SET PASSEDVALIDATION=0

    ECHO Validating %~1...

    IF "%~1"=="NUMCODE" (
        ECHO - Value: %NUMCODE%
        IF NOT "%NUMCODE%"=="" SET PASSEDVALIDATION=1
        IF "!PASSEDVALIDATION!"=="1" (
            CALL :IsNumeric %NUMCODE% RETVAL
            SET PASSEDVALIDATION=!RETVAL!
        )
        IF "!PASSEDVALIDATION!"=="1" (
            IF NOT %NUMCODE% GEQ 1 SET PASSEDVALIDATION=0
        )
        IF "!PASSEDVALIDATION!"=="1" (
            IF NOT %NUMCODE% LEQ 526 SET PASSEDVALIDATION=0
        )
        IF "!PASSEDVALIDATION!"=="0" (
            ECHO - The first parameter is invalid, it can not be blank.
            ECHO - Valid value is a number from 1 to 526.
            ECHO - Leading zeros are not valid.
        )
    )

    IF "%~1"=="NAME" (
        ECHO - Value: %NAME%
        IF NOT "%NAME%"=="" SET PASSEDVALIDATION=1
        IF "!PASSEDVALIDATION!"=="0" (
            ECHO - The second parameter is invalid, it can not be blank.
        )
    )

    IF "!PASSEDVALIDATION!"=="0" (
        ECHO - Failed validation.
        EXIT /B 1
    ) ELSE (
        ECHO - Passed validation.
    )
    EXIT /B 0

Usage Examples:

C:\mytestscript.bat 10 MrTest
Validating NUMCODE...
- Value: 10
- Passed validation.

Validating NAME...
- Value: MrTest
- Passed validation.

C:\mytestscript.bat 600
Validating NUMCODE...
- Value: 600
- The first parameter is invalid, it can not be blank.
- Valid value is a number from 1 to 526.
- Leading zeros are not valid.
- Failed validation.

C:\mytestscript.bat 10
Validating NUMCODE...
- Value: 10
- Passed validation.

Validating NAME...
- Value: 
- The second parameter is invalid, it can not be blank.
- Failed validation.

Upvotes: 0

hornzach
hornzach

Reputation: 295

You could try this. The variable passed is for example var and %var% is equal to 500.

set /a varCheck=%var%
if %varCheck% == %var% (goto :confirmed) else (exit /B)
exit /B

:confirmed
:: You can use %var% here, and it should only be executed if it is numerical!

if %var% is equal to e.g. a3453d, then it would set varCheck to be 0, and because 0 is not equal to a3453d, then it will exit batch processing.

(The exit on line 3 is just in case the if statement decides not to execute for some reason ... XD.)

Upvotes: 8

Andrew Dennison
Andrew Dennison

Reputation: 1089

@hornzach - You were so close and with a much simpler answer than the rest.

To hide the error message in (win 7 at least) redirect to the standard error output (2) to nul (a special file, that quietly discards the output "bit-bucket")

set /a varCheck = %var% 2>nul

Then the rest of your answer works for the 4 test cases.

Full Answer With Test Cases:

call :CheckNumeric AA  "#NOT A VALID NUMBER"
call :CheckNumeric A1  "#NOT A VALID NUMBER"
call :CheckNumeric 1A  "#NOT A VALID NUMBER"

call :CheckNumeric 11  "#A VALID NUMBER"

call :CheckNumeric 1.23456789012345678901234567890.123456  "#NOT A VALID NUMBER"
goto :EOF

:CheckNumeric
@ECHO.

@ECHO Test %1
set /a num=%1 2>nul

if {%num%}=={%1} (
    @ECHO %1 #A VALID NUMBER, Expected %2
    goto :EOF
)

:INVALID
    @ECHO %1 #NOT A VALID NUMBER, Expected %2

Outputs:

Test AA
AA #NOT A VALID NUMBER, Expected "#NOT A VALID NUMBER"

Test A1
A1 #NOT A VALID NUMBER, Expected "#NOT A VALID NUMBER"

Test 1A
1A #NOT A VALID NUMBER, Expected "#NOT A VALID NUMBER"

Test 11
11 #A VALID NUMBER, Expected "#A VALID NUMBER"

Test 1.23456789012345678901234567890.123456
1.23456789012345678901234567890.123456 #NOT A VALID NUMBER, Expected "#NOT A VALID NUMBER"

Upvotes: 5

Dharma Leonardi
Dharma Leonardi

Reputation: 101

Does the same thing as above. Have problems with special characters. However, the solution is of a different approach.

@echo off
cls
setlocal enabledelayedexpansion

if "%1"=="" (goto:eof) else (set _VAR2CHECK=%1)

for /l %%a in (0,1,9) do (
   if defined _VAR2CHECK (set "_VAR2CHECK=!_VAR2CHECK:%%a=!") else (goto :end)
)

:end
if defined _VAR2CHECK (echo %1 #NOT A VALID NUMBER) else (echo %1 #A VALID NUMBER)

set "_VAR2CHECK="
endlocal

Test scenarions:

C:\>ISNUM 1A
1A  #NOT A VALID NUMBER

C:\>ISNUM 11
11  #A VALID NUMBER

Upvotes: 2

Endoro
Endoro

Reputation: 37569

for ± integers (test also for leading zero):

echo(%~1|findstr "^[-][1-9][0-9]*$ ^[1-9][0-9]*$ ^0$">nul&&echo numeric||echo not numeric

Upvotes: 15

Magoo
Magoo

Reputation: 79983

SET "var="&for /f "delims=0123456789" %%i in ("%1") do set var=%%i
if defined var (echo %1 NOT numeric) else (echo %1 numeric)

Replace %1 with %yourvarname% as appropriate

Upvotes: 61

Related Questions