Überprüfen Sie die Batchdatei nur auf numerische Eingaben

10

Gibt es in der Windows NT-basierten Befehlszeile (hauptsächlich für XP oder höher) eine Möglichkeit zu überprüfen, ob es sich bei einem bereitgestellten Switch nur um eine Nummer handelt? Abhängig von der Anzahl möchte ich, dass der Code x mehrmals durchlaufen wird

Kanadischer Luke
quelle
1
Persönlich bevorzuge ich die Methode in dieser Antwort für: Stellen Sie sicher, dass der Benutzer eine Ganzzahl eingegeben hat . Verwenden Sie den Befehlsprozessor, um all diese Arbeiten auszuführen . Sie können es als minimale Lösung auf 2 x Zeilen vereinfachen: 1 . set /a NO_LINES=%~1; 2 if %NO_LINES% NEQ %~1 goto ABORT.. Wenn beide gleich sind - Die Variable oder der Parameter ist numerisch .
wird

Antworten:

18

Bearbeitet, um den regulären Ausdruck gemäß dem Kommentar von debham zu korrigieren . Es stellt sich heraus, dass das Hinzufügen eines Leerzeichens vor der Pipe nach dem Echo der Piping-Zeichenfolge ein Leerzeichen hinzufügt, was den Anfang / das Ende der Zeilenübereinstimmung zuvor unterbrochen hat. Die Regex könnte weiter verbessert werden, indem Leerzeichen am Anfang und am Ende verworfen werden.


Da ist der findstrBefehl. Es kann Dateien mit regulären Ausdrücken durchsuchen, ähnlich wie grepunter Linux. Es kann auch nach Piped-Eingaben suchen.

@echo off

set param=%1

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

if %errorlevel% equ 0 (
    echo Valid number
)

Erläuterung

Der verwendete Parameter wird in die paramVariable gesetzt. Es %1hindert Sie jedoch nichts daran, den Parameter direkt zu verwenden ( für den ersten Parameter).

findstrwird verwendet, um die Pipe-Eingabe mit dem /rFlag nach Regex zu durchsuchen .

Das Muster:

  • ^ bedeutet Zeilenanfang.

  • [0-9]bedeutet eine Ziffer. Dies *bedeutet, dass die vorherigen null oder mehrmals wiederholt wurden. Bedeutet [0-9][0-9]*also eine Ziffer plus null oder mehr Ziffern. Mit anderen Worten, mindestens eine Ziffer. Das +eine oder mehrere Mal scheint nicht von unterstützt zu werden findstr. Beachten Sie, dass [1-9]für die erste Ziffer führende Nullen nicht zugelassen werden - siehe Kommentare.

  • $ bedeutet Zeilenende.


Nun, eine for-Schleife im Batch für x- mal ... Wenn x keine gültige Zahl ist, wird die Schleife überhaupt nicht ausgeführt - sie wird nur für die nächste Zeile übersprungen. Es muss also nicht überprüft werden, ob die Eingabe eine gültige Nummer ist!

@echo off

set param=%1

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

Die Schleife wird durchgeführt, indem for /l, dh (x,y,z)Mittel beginnen bei x, um ybis zzum Erreichen erhöht wird. Und es wird %%aauf die aktuelle Nummer / Iteration gesetzt.

Hinweis: Dies schlägt tatsächlich fehl, wenn eine führende Null vorhanden ist, wodurch der Befehlsprozessor diese als Oktalzahl behandelt. Siehe dbenhams Antwort für eine bessere Lösung.

Bob
quelle
Hervorragende Erklärung! Und einfach zu bedienen
Kanadier Luke
1
Wie geschrieben, "this 1 fails"schlägt diese Lösung mit einem Parameter fehl, bei dem FINDSTR genau übereinstimmen sollte. Es sollte keine Wortübereinstimmung geben.
Dbenham
@ Benbenham Danke. Ich habe zuvor versucht, den Anfang / das Ende der Zeilenübereinstimmung zu finden, aber dies schlug fehl, weil das Echo ein zusätzliches Leerzeichen passierte. Jetzt behoben.
Bob
@CanadianLuke Vielleicht möchten Sie einen Blick auf die Bearbeitung werfen.
Bob
Ein Wert von 09oder 010kann aufgrund der Oktalschreibweise Probleme verursachen. Siehe meine Antwort für Regex, die die Oktalschreibweise nicht zulässt.
Dbenham
8

Das Folgende funktioniert sehr gut für mich. SET /a param=%1+0Gibt immer zurück, 0wenn %1es leer oder nicht numerisch ist. Andernfalls wird die angegebene Nummer angegeben.

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
Andreas
quelle
4
Dies schlägt fehl, wenn Parameter = 0. Behandelt auch einen Parameter wie "1 + 1" als Zahl, was je nach Anforderung zu Problemen führen kann.
Dbenham
7

Dadurch wird erkannt, ob der erste Parameter eine gültige natürliche Zahl (nicht negative Ganzzahl) ist.

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

Wenn Sie Anführungszeichen um die Zahl zulassen möchten, dann

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

Hinweis - führende Nullen sind nicht zulässig, da sie im Stapel als oktal behandelt werden. Ein Wert wie 09ist daher ungültig und 010hat den Wert 8.

Dbenham
quelle
3

Inspiriert von Bobs hervorragender Antwort mit den folgenden Ergänzungen

  • Korrigieren Sie die Fehlerlevel-Logik
  • Implementieren Sie eine DoWork-Schleife / ein DoWork-Sub, die die Zahl durchläuft und einige Arithmetiken ausführt

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

Das Problem mit dem Folgenden ist, dass es immer 'Gültige Zahl' zurückgibt, weil 'wenn Fehlerstufe 0' immer wahr ist, da es sich um einen '> = 0'-Vergleich handelt, nicht um einen' == 0'-Vergleich.

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

meine $ .02

KeyboardJockey
quelle
Whoops ... hat den Fehlerlevel auch bei mir behoben. Direkter numerischer Vergleich statt automatischem Durchfall.
Bob
2

Sie können jede Variable überprüfen, wenn ihre Nummer:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")
Krzysztof Gapski
quelle
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
quelle
2
Können Sie bitte auch eine Erklärung hinzufügen?
Slhck
0

Ich weiß nicht warum, aber auf meinem System hat der findstrBefehl nicht funktioniert. Die Fehlerstufe wurde beim Spiel nicht oder nicht geändert.

Ich habe mir allerdings eine andere Methode ausgedacht

:: 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
quelle
-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.

Hier ist ein Spiel, das diese Funktion verwendet.

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