Verifica apenas a entrada numérica no arquivo de lote

8

Na linha de comando baseada no Windows NT (principalmente para XP ou superior), existe uma maneira de verificar se um switch sendo fornecido é apenas um número? Dependendo do número, eu quero fazer um loop através do código x número de vezes

    
por Canadian Luke 24.03.2012 / 18:04

8 respostas

15

Editado para corrigir o regex conforme comentário do debham . Acontece que adicionar um espaço antes do pipe após o echo adiciona um espaço à string canalizada, que foi o que quebrou o início / fim da linha correspondente anteriormente. O regex pode ser melhorado, descartando-se o espaço em branco no início e no final.

Existe o comando findstr . Ele pode pesquisar arquivos com expressões regulares, muito parecido com grep no Linux. Também pode pesquisar a entrada canalizada.

@echo off

set param=%1

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

if %errorlevel% equ 0 (
    echo Valid number
)

Explicação

O parâmetro usado é definido na variável param . No entanto, não há nada que o impeça de usar o parâmetro diretamente ( %1 para o primeiro parador).

findstr é usado para pesquisar a entrada canalizada com o sinal /r para regex.

O padrão:

  • ^ significa início de linha.

  • [0-9] significa um dígito. O * significa o zero repetido anterior ou mais vezes. Então, [0-9][0-9]* significa um dígito, mais zero ou mais dígitos. Em outras palavras, pelo menos um dígito. O + uma ou mais vezes parece não ser suportado por findstr . Observe que [1-9] é usado para o primeiro dígito para não permitir zeros à esquerda - consulte os comentários.

  • $ significa fim de linha.

Agora, um loop for em lote para x número de vezes ... se x não for um número válido, o loop na verdade não será executado - apenas é pulado para a próxima linha. Portanto, não há necessidade de verificar se a entrada é um número válido!

@echo off

set param=%1

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

O loop é feito usando for /l , onde (x,y,z) significa iniciar em x , incrementar em y até que z seja atingido. E define %%a para o número / iteração atual.

Nota: isso realmente falha se houver um zero à esquerda, fazendo com que o processador de comandos o trate como um número octal. Veja a resposta do dbenham para uma melhor solução.

    
por 24.03.2012 / 18:57
7

O seguinte funciona muito bem para mim. SET /a param=%1+0 sempre retorna 0 se %1 estiver vazio ou não numérico. Caso contrário, fornece o número fornecido.

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
    
por 19.02.2013 / 17:28
6

Isso detectará se o primeiro parâmetro é um número natural válido (inteiro não negativo).

@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
)

Se você quiser permitir cotações em torno do número,

@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
)

Os zeros à esquerda da nota não são permitidos porque o lote os trata como octal, portanto, um valor como 09 é inválido e 010 tem um valor de 8.

    
por 11.07.2013 / 14:16
2

Inspirado pela resposta excelente de Bob com as seguintes adições

  • Corrija a lógica do nível de erro
  • Implementar um loop / subdo DoWork que percorre o número e faz alguma aritmética
:::::::::::::::
::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^>

O problema com o seguinte é que ele sempre retorna 'Número válido' porque 'se errorlevel 0' é sempre verdadeiro devido ao fato de ser uma comparação '> = 0', não uma comparação '== 0' .

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

my $ .02

    
por 29.12.2014 / 23:48
1

Você pode validar qualquer variável se o seu número:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")
    
por 08.10.2014 / 12:20
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
    
por 25.07.2014 / 11:22
0

Eu não sei porque, mas no meu sistema o comando findstr não funcionou. O nível de erro não estava sendo alterado na correspondência ou sem correspondência.

Eu criei outro método embora

:: 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
)
    
por 21.08.2015 / 18:18
-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.

Aqui está um jogo que usa essa função.

@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
    
por 03.09.2014 / 11:31