【问题标题】:How to check if a parameter (or variable) is a number in a Batch script如何检查参数(或变量)是否是批处理脚本中的数字
【发布时间】:2013-07-11 02:54:58
【问题描述】:

我需要检查传递给 Windows 批处理文件的参数是否为数值。检查也适用于变量会很好。

我发现answer 与类似的question 相似,其中findstr 命令与正则表达式一起使用。

我确实尝试了该解决方案,但它并没有像我希望的那样工作(至少在 Windows 7 上)。

我的测试场景如下:

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

11  # a valid number

【问题讨论】:

  • 对其他读者的注意:这个问题可以并且已经被多种方式解释。下面的一些答案是测试 CMD.EXE 可以接受的数字。其他答案正在测试“数字”的其他定义,例如原始问题中给出的定义。哪个答案最好取决于一个人的需要。做出明智的选择。 :-)

标签: windows batch-file variables


【解决方案1】:
SET "var="&for /f "delims=0123456789" %%i in ("%1") do set var=%%i
if defined var (echo %1 NOT numeric) else (echo %1 numeric)

酌情将%1替换为%yourvarname%

【讨论】:

  • +1 但也用双引号将"var=%%i" 括起来可以防止一些有毒字符。
  • 就我而言,不再在 Windows 10 中工作。如果我为 %yourvarname% 分配一个数值,则未定义 var。有什么想法吗?
  • @nst1nctz:对我来说工作得非常愉快 - 请举例说明它失败的值。请注意,如果%1 是数字,则var 设计为未定义,如果%1 是数字则定义。
  • 人们应该始终质疑自己的代码——我仍在学习永远不要相信自己的工作。 +1
  • @MikeQ:批处理通常是这样的。考虑这是一个模板。首先,%1 是批处理过程的第一个参数,因此call :chknumeric %varname% 将用varname 的值替换%1 在活动行之前加上标签:chknumeric & 将goto :eof 放在下一行 &您有一个返回var 的程序。该例程针对数字字符串,例如将处理条形码数字。如果愿意,可以将var 更改为notnumeric - 但var 可以检查“。”测试单个小数点。或针对不同的字符集 & 逻辑名称再次更改
【解决方案2】:

对于± integers也测试前导零):

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

【讨论】:

  • +1,虽然如果传递"this&that" 之类的参数会出现问题。更多的工作可以解决这个问题;)
  • @dbenham 是的。最好的方法是在 Regex 中引用和添加一些点。谢谢。
  • @Endoro:这个命令也能正确处理毒字符:echo("%~1"|findstr "^[\"][-][1-9][0-9]*[\"]$ ^[\"][1-9][0-9]*[\"]$ ^[\"]0[\"]$">nul&&echo numeric||echo not numeric
【解决方案3】:

你可以试试这个。传递的变量例如是var%var% 等于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!

如果%var% 等于例如a3453d,则将varCheck设置为0,由于0不等于a3453d,则退出批处理。

(第 3 行的退出是为了以防 if 语句由于某种原因决定不执行……XD。)

【讨论】:

  • 您的解决方案在场景 #3 中失败。它显示以下错误并终止批处理执行。错误:“无效数字。数字常量是十进制 (17)、十六进制 (0x11) 或八进制 (021)。(此时回显是意外的。”
  • 该死..我不知道...我会问我的一个朋友,他是批处理文件的专家。
【解决方案4】:

最简单的正整数应该是:

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

如果还要考虑负数(连字符),这将起作用

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

this article here学习

【讨论】:

  • 很高兴知道,但仅供参考,这仅适用于整数。如果您需要支持小数,请查看其他答案。
  • 哦,这太酷了,谢谢你的发帖!这正是我需要的(对于整数)。非常干净简洁。
  • 仅供参考,对于 CMD 可以接受的一些极端情况,这将失败:八进制 (020) 和十六进制 (0x10)。正零 (+0)。反复否定(CMD 将--5 视为 5)。这可能对一个人的需求并不重要,但值得一提。总的来说,它工作得很好,而且代码很少。
【解决方案5】:

@hornzach - 你是如此亲密,而且答案比其他人简单得多。

隐藏错误消息(至少是win 7)重定向到标准错误输出(2)到nul(一个特殊的文件,它悄悄地丢弃输出“bit-bucket”)

set /a varCheck = %var% 2>nul

那么您的其余答案适用于 4 个测试用例。

完整的测试用例答案:

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

输出:

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"

【讨论】:

  • 此代码对所有带有 1 个或多个前导零(如 05 或 009)的数字产生错误的结果,因为 Windows 命令处理器使用 C 函数 strtol 将字符串转换为 32 位有符号整数和函数参数base 具有价值 0(自动基础)。因此,我的两个示例的字符串比较是{5}=={05}(删除了前导零)和{}=={009}。变量 num 仍未为 009 定义(或在已定义的情况下保留其当前值),因为 009 是无效的八进制数。
  • 您可以测试租赁 0,例如if "%SIZE:~0,1%"=="0" (echo ERROR: %SIZE% is not a valid number & pause & goto :BEGIN)
  • 好点@Mofi:+1 ...但在用例中不需要:只是十进制数字(假设)
  • @Cestarian - 这取决于SET /A 导致 CMD.EXE 计算算术表达式的事实。它在这样的表达式中计算原始变量%var%,并将结果存储在第二个变量%varCheck% 中,然后比较这两个变量。如果它们不同,CMD 会将其评估为不同的值,这通常意味着原始值是非数字的。例如,如果您向 CMD 询问字符串 "example" 的数值,CMD 将返回 0(零)。由于"example"0 不是同一个值,我们可以假设给出了一个非数字值。
【解决方案6】:

做和上面一样的事情。特殊字符有问题。但是,解决方案是不同的方法。

@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

测试场景:

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

C:\>ISNUM 11
11  #A VALID NUMBER

【讨论】:

    【解决方案7】:

    只需尝试除以 1。 但它不适用于 Z 以外的数字(非相对整数或小数)。

    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)
    

    【讨论】:

      【解决方案8】:

      我改用这个函数,它似乎对我有用,没有任何问题...

      脚本 (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
      

      用法示例:

      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.
      

      【讨论】:

        【解决方案9】:

        我使用技术含量更低的方法。它仅适用于整数并支持负值。

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

        第一行获取命令行参数并将其放入 XVALUE。使用“引号”可以防止各种特殊字符出现问题。

        第二行看起来很神秘,但当 SET /A 等号右侧的文本字符串被解释为包含数值的环境变量时,它利用了这一点。命令处理器解析假定的数值而不生成任何错误消息或设置 ERRORLEVEL。这样做总是会导致 XVALUE 被转换为有效的数值,无论传递给我们什么。

        第三行是可选的,仅当您想严格要求参数是 -2147483648 到 2147483647 范围内的数值时才需要。如果您不使用 if 测试,那么

        • 您可以通过为八进制和十六进制数字添加前缀 0 或 0x 来支持它们。
        • 如果有人使用非常小或非常大的数字,例如 -9999999999999 或 9999999999999,则 XVALUE 将设置为允许的最小值或最大值,即 -2147483648 和 2147483647。
        • 如果有人使用诸如“hello”之类的垃圾,则 XVALUE 设置为 0。如果它类似于 123x456,则解析器在“x”处停止,XVALUE 设置为 123。

        【讨论】:

          【解决方案10】:

          if errorlevel 只接受可用于检查的数值:

          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
          )
          

          第一次检查会通过,第二次不会。 虽然上面的脚本不能处理一元 + - 如果你也想处理这种情况,请检查 - isInteger.bat

          【讨论】:

            猜你喜欢
            • 2017-09-06
            • 2010-12-02
            • 1970-01-01
            • 1970-01-01
            • 2012-10-20
            • 1970-01-01
            • 1970-01-01
            • 2021-03-15
            • 2014-05-09
            相关资源
            最近更新 更多