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


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.


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

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.


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 $


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

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

-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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.