仅检查批处理文件中的数字输入


10

在基于Windows NT的命令行中(大多数用于XP或更高版本),是否可以验证提供的开关是否仅是数字?根据数量,我希望它循环遍历代码x


1
就个人而言,我更喜欢以下答案中的方法:确保用户输入了integer。使用命令处理器来完成所有工作。您可以将其简化为2 x线作为最小解决方案:1 set /a NO_LINES=%~1.; 2 if %NO_LINES% NEQ %~1 goto ABORT。当两者相等时-变量或参数为数字

Answers:


18

根据debham的评论进行编辑以修复正则表达式。事实证明,在回声之后在管道之前添加一个空格会在管道字符串中添加一个空格,这破坏了之前的行匹配的开始/结束。通过在开头和结尾处丢弃空格可以进一步改善正则表达式。


findstr命令。它可以搜索带有正则表达式的文件,就像grep在Linux中一样。它还可以搜索管道输入。

@echo off

set param=%1

echo %param%| findstr /r "^[1-9][0-9]*$">nul

if %errorlevel% equ 0 (
    echo Valid number
)

说明

使用的参数设置在param变量中。但是,没有什么可以阻止您直接使用参数(%1对于第一个参数)。

findstr用于搜索带有/r标志的管道输入的正则表达式。

模式:

  • ^ 表示行首。

  • [0-9]表示一个数字。在*前面的手段重复零次或更多次。因此[0-9][0-9]*表示一位数字,再加上零个或多个数字。换句话说,至少一个数字。在+一次或多次,似乎并没有被支持findstr。请注意,[1-9]第一个数字用于禁止前导零-请参见注释。

  • $ 表示行尾。


现在,一个for循环分批执行了x次...如果x不是有效数字,则该循环实际上根本不会运行-只会跳过下一行。因此,无需检查输入的数字是否有效!

@echo off

set param=%1

for /l %%a in (1,1,%param%) do (
    echo %%a
)

使用来完成循环for /l,其中的(x,y,z)意思是从处开始x,递增y直到z达到。并设置%%a为当前编号/迭代次数。

注意:如果有前导零,则此操作实际上会失败,从而导致命令处理器将其视为八进制数。请参阅dbenham的答案以获得更好的解决方案。


极好的解释!且易于使用
加拿大卢克

1
如所写,此解决方案将失败,并使用诸如"this 1 fails"FINDSTR之类的参数进行精确匹配。它不应该单词匹配。
dbenham

@dbenham谢谢。我之前尝试过行匹配的开始/结束,但是由于回声传递了多余的空间而失败了。立即修复。
鲍勃,

@CanadianLuke您可能希望看一下编辑。
鲍勃,

09010可能由于八进制表示法而引起问题。请参阅关于不允许八进制表示法的正则表达式的答案
dbenham 2013年

8

以下对我来说非常有效。如果为空或非数字,则SET /a param=%1+0始终返回。否则,它将提供给定的号码。0%1

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number

4
如果parameter = 0,则此操作将失败。还将根据要求将“ 1 + 1”之类的参数视为数字,这可能会引起问题。
dbenham

7

这将检测第一个参数是否为有效的自然数(非负整数)。

@echo off
echo %1|findstr /xr "[1-9][0-9]* 0" >nul && (
  echo %1 is a valid number
) || (
  echo %1 is NOT a valid number
)

如果您想在数字前后加上引号,则

@echo off
echo "%~1"|findstr /xr /c:\"[1-9][0-9]*\" /c:\"0\" >nul && (
  echo %~1 is a valid number
) || (
  echo %~1 is NOT a valid number
)

注意-不允许使用前导零,因为批处理会将其视为八进制,因此值like 09无效,并且010值为8。


3

受到鲍勃出色回答的启发,并增加了以下内容

  • 修复错误级别逻辑
  • 实现一个遍历数字并进行一些算术运算的DoWork循环/子程序

:::::::::::::::
::CountTo.bat
:::::::::::::::
@echo off

::This is the number to test
if "%1"=="" goto :Usage

set param=%1
set matchPattern="^[1-9][0-9]*$"

::test if param matches matchPattern, quietly
:: (redirect stdout to nul, and stderr to stdout)

echo %param%|findstr /r %matchPattern%>nul 2>&1

:: check for errorlevel 1 or higher.  errorlevel 0 is handled as
:: an unchecked fall-through
if errorlevel 1 goto :MyHandleErrorCode

::Success (errorlevel ! >= 1) so proceed.
echo %param% is a valid number
echo  (matches findstr /r %param% %matchPattern%)
echo  findstr returned errorlevel 0

::any other code that the batch file needs to do goes here
echo.
echo Iterating from 1 to %param%
echo.
for /l %%i in (1,1,%param%) do call :DoWork %%i

::anything else,
:: .
:: .

::cleanup
:: .
:: .

::exit the batch file here, skipping embedded subroutines
goto :eof

:::::::::::::::::::::::::
:: Main work subroutine
:::::::::::::::::::::::::
:DoWork
set /a offset = %1 - 1
set /a square = %1 * %1
echo item %1
echo   offset: %offset%
echo   square: %square%
echo.
goto :eof

:::::::::::::::::::::::
:: Error handler code
:::::::::::::::::::::::
:MyHandleErrorCode
echo.
echo CountTo %param%
echo   %param% is not a valid number
echo   (does not match findstr /r %param% %matchPattern%)
echo   findstr returned errorlevel ^>= 1
:: error code doesn't have a goto :eof, we want to drop through to :Usage

::::::::
:Usage
::::::::
echo.
echo Usage:
echo.   CountTo ^<someNumber^>

以下问题是它始终返回“有效数字”,因为“ if errorlevel 0”始终为true,这是因为它是一个“> = 0”比较,而不是“ == 0”比较。

@echo off

set param=%1

echo %param%| findstr /r "^[1-9][0-9]*$">nul

if errorlevel 0 (
    echo Valid number
)

我的$ .02


糟糕...也修复了我的错误级别。直接数值比较,而不是自动下降。
鲍勃,


0
set xx=33
echo %xx%
SET /a %xx%+0 2>nul >nul && echo all Digits


set xx=3x3
echo %xx%
SET /a %xx%+0 2>nul >nul || echo No Digits

2
您也可以补充一些解释吗?
slhck

0

我不知道为什么,但是在我的系统上该findstr命令不起作用。匹配或不匹配时未更改错误级别。

我确实想出了另一种方法

:: Look for all digits. Parse the string and use all the digits as
:: delimiters. If the entire string is a digit then we will get an empty
:: parse value.
SET ALL_DIGITS=0
FOR /F "tokens=* delims=0123456789" %%a IN ("%VALUE%") DO (
    IF "[%%a]" EQU "[]" SET ALL_DIGITS=1
)

IF %ALL_DIGITS% EQU 0 (
    ECHO ERROR: %VALUE% is not all numbers
)

-1
:main 
set /p input=text
if %input% equ 0 goto valid
set /a inputval="%input%"*1
if %inputval% equ 0 goto invalid
goto valid

:invalid
echo Input is not an integer.

:valid
echo Input is an integer.

这是使用此功能的游戏。

@echo off
:main
set /a guessmin=1
set /a guessmax=100
set /a guessrand=%random% %%100 +1
echo.
:check
if %guessmin% equ %guessmax% goto fail
set /p input=- Pick a number %guessmin% - %guessmax%: 
set /a inputval="%input%"*1
if %inputval% equ 0 goto invalid
if %inputval% gtr %guessmax% goto invalid
if %inputval% lss %guessmin% goto invalid
if %inputval% gtr %guessrand% goto high
if %inputval% lss %guessrand% goto low
if %inputval% equ %guessrand% goto mid
:invalid
echo   Please enter a valid number.
echo.
goto check
:high
echo   Your guess was too high.
echo.
set /a guessmax=%inputval%-1
goto check
:low
echo   Your guess was too low.
echo.
set /a guessmin=%inputval%+1
goto check
:mid
echo   Your guess was correct. The game will now reset.
set /p input=- Press enter to play again.
cls
goto main
:fail
echo   You actually managed to lose because there is only
echo   one number remaining. That number is %guessrand%.
set /p input=- Press enter to lose again.
cls
goto main
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.