Verifique apenas a entrada numérica no arquivo em lotes
10
Na linha de comando baseada no Windows NT (principalmente para XP ou superior), existe uma maneira de verificar se uma opção fornecida é apenas um número? Dependendo do número, quero que ele percorra o código x várias vezes
Pessoalmente, prefiro o método nesta resposta para: Verifique se o usuário digitou um número inteiro . Use o processador de comandos para fazer todo esse trabalho. Você pode simplificá-lo para 2 x linhas como uma solução mínima: 1 set /a NO_LINES=%~1.; 2 if %NO_LINES% NEQ %~1 goto ABORT. Quando os dois são iguais - A variável ou parâmetro é numérico .
vai
Respostas:
18
Editado para corrigir a regex de acordo com o comentário de debham . Acontece que adicionar um espaço antes do tubo após eco adiciona um espaço à cadeia de tubulação, que foi o que quebrou o início / fim da linha correspondente anteriormente. A regex pode ser melhorada ainda mais descartando os espaços em branco no início e no final.
Aí está o findstrcomando. Pode pesquisar arquivos com expressões regulares, como grepno Linux. Também pode pesquisar 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 paramvariável No entanto, não há nada impedindo você de usar o parâmetro diretamente ( %1para o primeiro paramater).
findstré usado para pesquisar a entrada canalizada com o /rsinalizador para regex.
O padrão:
^ significa início da linha.
[0-9]significa um dígito. Os *meios que o anterior repetiu zero ou mais vezes. Isso [0-9][0-9]*significa um dígito, mais zero ou mais dígitos. Em outras palavras, pelo menos um dígito. A +uma ou mais vezes não parece ser suportada por findstr. Observe que [1-9]é usado no primeiro dígito para não permitir zeros à esquerda - veja os comentários.
$ significa fim da linha.
Agora, um loop for em lote por x número de vezes ... se x não for um número válido, o loop na verdade não será executado - ele será ignorado na 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 start at x, incremento de yaté que zseja atingido. E define %%ao 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 solução melhor.
Conforme escrito, esta solução falhará com um parâmetro como "this 1 fails"The FINDSTR deve fazer uma correspondência exata. Não deve corresponder a uma palavra.
dbenham
@dbenham Obrigado. Eu tentei a correspondência de início / fim de linha antes, mas isso falhou devido ao eco passando um espaço extra. Corrigido agora.
11113 Bob
@CanadianLuke Você pode dar uma olhada na edição.
11113 Bob
Um valor 09ou 010pode causar problemas devido à notação octal. Veja minha resposta para regex que não permite a notação octal.
dbenham
8
O seguinte funciona muito bem para mim. SET /a param=%1+0sempre retorna 0se %1estiver vazio ou não numérico. Caso contrário, ele fornece o número fornecido.
SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
Inspirado pela excelente resposta de Bob com as seguintes adições
Corrija a lógica do nível de erro
Implemente um loop / sub DoWork que itera pelo 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 o nível de erro 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
)
Você pode adicionar alguma explicação também, por favor?
slhck 25/07
0
Não sei por que, mas no meu sistema o findstrcomando não funcionou. O nível de erro não estava sendo alterado na correspondência ou não.
Eu vim com 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
)
: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
set /a NO_LINES=%~1
.; 2if %NO_LINES% NEQ %~1 goto ABORT
. Quando os dois são iguais - A variável ou parâmetro é numérico .Respostas:
Editado para corrigir a regex de acordo com o comentário de debham . Acontece que adicionar um espaço antes do tubo após eco adiciona um espaço à cadeia de tubulação, que foi o que quebrou o início / fim da linha correspondente anteriormente. A regex pode ser melhorada ainda mais descartando os espaços em branco no início e no final.
Aí está o
findstr
comando. Pode pesquisar arquivos com expressões regulares, comogrep
no Linux. Também pode pesquisar entrada canalizada.Explicação
O parâmetro usado é definido na
param
variável No entanto, não há nada impedindo você de usar o parâmetro diretamente (%1
para o primeiro paramater).findstr
é usado para pesquisar a entrada canalizada com o/r
sinalizador para regex.O padrão:
^
significa início da linha.[0-9]
significa um dígito. Os*
meios que o anterior repetiu zero ou mais vezes. Isso[0-9][0-9]*
significa um dígito, mais zero ou mais dígitos. Em outras palavras, pelo menos um dígito. A+
uma ou mais vezes não parece ser suportada porfindstr
. Observe que[1-9]
é usado no primeiro dígito para não permitir zeros à esquerda - veja os comentários.$
significa fim da linha.Agora, um loop for em lote por x número de vezes ... se x não for um número válido, o loop na verdade não será executado - ele será ignorado na próxima linha. Portanto, não há necessidade de verificar se a entrada é um número válido!
O loop é feito usando
for /l
, onde(x,y,z)
significa start atx
, incremento dey
até quez
seja atingido. E define%%a
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 solução melhor.
fonte
"this 1 fails"
The FINDSTR deve fazer uma correspondência exata. Não deve corresponder a uma palavra.09
ou010
pode causar problemas devido à notação octal. Veja minha resposta para regex que não permite a notação octal.O seguinte funciona muito bem para mim.
SET /a param=%1+0
sempre retorna0
se%1
estiver vazio ou não numérico. Caso contrário, ele fornece o número fornecido.fonte
Isso detectará se o primeiro parâmetro é um número natural válido (número inteiro não negativo).
Se você deseja permitir aspas ao redor do número,
Nota - zeros à esquerda são desaprovados porque o lote os trata como octais, portanto, um valor como
09
é inválido e010
tem um valor de 8.fonte
Inspirado pela excelente resposta de Bob com as seguintes adições
O problema com o seguinte é que ele sempre retorna 'Número válido' porque 'se o nível de erro 0' sempre é verdadeiro devido ao fato de ser uma comparação '> = 0', não uma comparação '== 0'.
meu $ .02
fonte
Você pode validar qualquer variável se seu número:
fonte
fonte
Não sei por que, mas no meu sistema o
findstr
comando não funcionou. O nível de erro não estava sendo alterado na correspondência ou não.Eu vim com outro método embora
fonte
Aqui está um jogo que usa essa função.
fonte