Vérifier uniquement l'entrée numérique dans le fichier de commandes

10

Dans la ligne de commande basée sur Windows NT (principalement pour XP ou supérieur), existe-t-il un moyen de vérifier si un commutateur fourni est un nombre uniquement? Selon le nombre, je veux qu'il boucle le code x nombre de fois

Canadian Luke
la source
1
Personnellement, je préfère la méthode dans cette réponse pour: Assurez-vous que l'utilisateur a entré un entier . Utilisez le processeur de commandes pour faire tout ce travail. Vous pouvez le simplifier en 2 x lignes comme solution minimale: 1 set /a NO_LINES=%~1.; 2 if %NO_LINES% NEQ %~1 goto ABORT.. Lorsque les deux sont égaux - La variable ou le paramètre est numérique .
le

Réponses:

18

Modifié pour corriger l'expression régulière selon le commentaire de Debham . Il s'avère que l'ajout d'un espace avant le tuyau après l'écho ajoute un espace à la chaîne canalisée, ce qui a rompu la correspondance de début / fin de ligne précédemment. Le regex pourrait être encore amélioré en supprimant les espaces blancs au début et à la fin.


Voilà la findstrcommande. Il peut rechercher des fichiers avec des expressions régulières, un peu comme grepsous Linux. Il peut également rechercher une entrée canalisée.

@echo off

set param=%1

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

if %errorlevel% equ 0 (
    echo Valid number
)

Explication

Le paramètre utilisé est défini dans la paramvariable. Cependant, rien ne vous empêche d'utiliser directement le paramètre ( %1pour le premier paramètre).

findstrest utilisé pour rechercher l'entrée canalisée avec le /rdrapeau pour regex.

Le motif:

  • ^ signifie début de ligne.

  • [0-9]signifie un chiffre. Le *signifie la précédente répétée zéro ou plusieurs fois. Signifie donc [0-9][0-9]*un chiffre, plus zéro ou plusieurs chiffres. En d'autres termes, au moins un chiffre. La +ou les fois ne semblent pas être prises en charge par findstr. Notez qu'il [1-9]est utilisé pour le premier chiffre pour interdire les zéros non significatifs - voir les commentaires.

  • $ signifie fin de ligne.


Maintenant, une boucle for en lot pour x nombre de fois ... si x n'est pas un nombre valide, la boucle ne s'exécute pas du tout - elle est simplement ignorée pour la ligne suivante. Il n'est donc pas nécessaire de vérifier si l'entrée est un nombre valide!

@echo off

set param=%1

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

La boucle se fait en utilisant for /l, où les (x,y,z)moyens commencent à x, incrémenter yjusqu'à ce que zsoit atteint. Et il définit %%ale nombre / itération actuel.

Remarque: cela échoue en fait s'il y a un zéro en tête, ce qui oblige le processeur de commandes à le traiter comme un nombre octal. Voir la réponse de dbenham pour une meilleure solution.

Bob
la source
Excellente explication! Et facile à utiliser
Canadian Luke
1
Comme écrit, cette solution échouera avec un paramètre tel que "this 1 fails"FINDSTR devrait faire une correspondance exacte. Il ne doit pas faire de correspondance de mots.
dbenham
@dbenham Merci. J'ai essayé la correspondance de début / fin de ligne avant, mais cela a échoué en raison de l'écho passant un espace supplémentaire. Fixé maintenant.
Bob
@CanadianLuke Vous voudrez peut-être jeter un œil à la modification.
Bob
Une valeur de 09ou 010pourrait causer des problèmes en raison de la notation octale. Voir ma réponse pour regex qui interdit la notation octale.
dbenham
8

Ce qui suit fonctionne très bien pour moi. SET /a param=%1+0renvoie toujours 0si %1est vide ou non numérique. Sinon, il fournit le numéro donné.

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
Andreas
la source
4
Cela échouera si paramètre = 0. Traitera également un paramètre comme "1 + 1" comme un nombre, ce qui pourrait poser des problèmes, selon les besoins.
dbenham
7

Cela détectera si le premier paramètre est un nombre naturel valide (entier non négatif).

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

Si vous souhaitez autoriser des guillemets autour du nombre, alors

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

Remarque - les zéros non significatifs sont interdits parce que le lot les traite comme octaux, donc une valeur comme 09n'est pas valide et 010a une valeur de 8.

dbenham
la source
3

Inspiré par l' excellente réponse de Bob avec les ajouts suivants

  • Correction de la logique de niveau d'erreur
  • Implémentez une boucle / un sous-programme DoWork qui parcourt le nombre et fait de l'arithmétique

:::::::::::::::
::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^>

Le problème avec ce qui suit est qu'il retourne toujours «Numéro valide» car «si le niveau d'erreur 0» est toujours vrai car il s'agit d'une comparaison «> = 0», et non d'une comparaison «== 0».

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

mon 0,02 $

KeyboardJockey
la source
Oups ... corrigé le niveau d'erreur sur le mien aussi. Comparaison numérique directe plutôt que le passage automatique.
Bob
2

Vous pouvez valider n'importe quelle variable si son nombre:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")
Krzysztof Gapski
la source
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
Gregor Weertman
la source
2
Pouvez-vous également ajouter quelques explications, s'il vous plaît?
slhck
0

Je ne sais pas pourquoi mais sur mon système, la findstrcommande n'a pas fonctionné. Le niveau d'erreur n'était pas modifié lors d'une correspondance ou d'aucune correspondance.

J'ai trouvé une autre méthode

:: 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
)
John Rocha
la source
-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.

Voici un jeu qui utilise cette fonction.

@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
SoaringMoon
la source