Validación de entrada de archivos por lotes: asegúrese de que el usuario haya ingresado un número entero

Resuelto Ben Brandt asked hace 15 años • 17 respuestas

Estoy experimentando con un archivo por lotes de Windows para realizar una operación simple que requiere que el usuario ingrese un número entero no negativo. Estoy usando técnicas simples de archivos por lotes para obtener la entrada del usuario:

@ECHO OFF
SET /P UserInput=Please Enter a Number: 

El usuario puede ingresar cualquier texto que desee aquí, por lo que me gustaría agregar alguna rutina para asegurarme de que lo que el usuario ingresó sea un número válido. Es decir... ingresaron al menos un carácter, y cada carácter es un número del 0 al 9. Me gustaría algo en lo que pueda introducir UserInput. Al final de la rutina sería como si/entonces que ejecutaría diferentes declaraciones en función de si era o no un número válido.

He experimentado con bucles y subcadenas y cosas así, pero mi conocimiento y comprensión aún son escasos... por lo que agradecería cualquier ayuda.

Podría crear un ejecutable y sé que hay formas mejores de hacer las cosas que los archivos por lotes, pero al menos para esta tarea estoy tratando de mantenerlo simple usando un archivo por lotes.

Ben Brandt avatar Mar 26 '09 09:03 Ben Brandt
Aceptado

Gracias a todos. Estaba tratando de ponérmelo más difícil al observar los bucles y la manipulación de cadenas. Utilicé tus consejos sobre evaluación y comparación de matemáticas. Esto es lo que finalmente se me ocurrió como guión conceptual:

:Top
@ECHO OFF
ECHO.
ECHO ---------------------------------------
SET /P UserInput=Please Enter a Number: 
ECHO.
ECHO UserInput = %UserInput%
ECHO.
SET /A Evaluated=UserInput
ECHO Math-Evaluated UserInput = %Evaluated%
if %Evaluated% EQU %UserInput% (
    ECHO Integer
    IF %UserInput% GTR 0 ( ECHO Positive )
    IF %UserInput% LSS 0 ( ECHO Negative )
    IF %UserInput% EQU 0 ( ECHO Zero )
    REM - Other Comparison operators for numbers
    REM - LEQ - Less Than or Equal To
    REM - GEQ - Greater Than or Equal To
    REM - NEQ - Not Equal To
) ELSE (
    REM - Non-numbers and decimal numbers get kicked out here
    ECHO Non-Integer
)

GOTO Top

Este método captura todos los números y puede detectar si son positivos, negativos o cero. Cualquier decimal o cadena se detectará como no entero. El único caso extremo que he encontrado es una cadena con espacios. Por ejemplo, el texto "Número 1" hará que el script se bloquee/cierre cuando la entrada del usuario se evalúe como matemática. Pero en mi situación, esto está bien. No quiero que mi script continúe con entradas no válidas.

Ben Brandt avatar Mar 26 '2009 10:03 Ben Brandt

También puedes utilizar un truco bastante sencillo:

echo %userinput%|findstr /r /c:"^[0-9][0-9]*$" >nul
if errorlevel 1 (echo not a number) else (echo number)

Esto utiliza findstrlas capacidades de coincidencia de expresiones regulares de '. No son muy impresionantes pero a veces son útiles.

Joey avatar Mar 25 '2010 13:03 Joey

Esta es la misma idea que la de Johannes. SET /A establece un valor numérico. Si la entrada no es un número, lo cambia a 0. Eso es lo que puedes aprovechar aquí para hacer tu verificación.

@ECHO OFF
SET /P UserInput=Please Enter a Number:
IF %UserInput% EQU 0 GOTO E_INVALIDINPUT

SET /A UserInputVal="%UserInput%"*1
IF %UserInputVal% GTR 0 ECHO UserInput "%UserInputVal%" is a number
IF %UserInputVal% EQU 0 ECHO UserInput "%UserInputVal%" is not a number
GOTO EOF

:E_INVALIDINPUT
ECHO Invalid user input
 
:EOF

Como alternativa, siempre puedes crear un pequeño archivo javascript y llamarlo desde tu archivo por lotes. Con parseInt() puedes forzar que la entrada sea un número entero, o puedes ejecutar tu propia función para probar la entrada.

Escribir javascript es tan rápido como el archivo por lotes, pero es mucho más poderoso. No se requiere IDE ni compilador; el bloc de notas servirá. Se ejecuta en todos los cuadros de Windows, al igual que sus archivos por lotes. Entonces, ¿por qué no utilizarlo?

Incluso puedes mezclar archivos por lotes y javascript. Ejemplo:

Contenido de sleep.js:

var SleepSecs=WScript.Arguments.Item(0);
WScript.Sleep(SleepSecs*1000)

Contenido de sleep.cmd:

cscript /nologo sleep.js %1

Ahora puede llamar a esto desde un archivo por lotes para que su script duerma durante 10 segundos. Algo así es difícil de hacer con un simple archivo por lotes.

sleep 10
Wouter van Nifterick avatar Mar 26 '2009 03:03 Wouter van Nifterick

Como señaló Ghostdog74, las respuestas publicadas por Joey el 26 de marzo de 2009 (puntuación 10) y Wouter van Nifterick el 26 de marzo de 2009 (puntuación 5) no funcionan.

La respuesta publicada por Joey el 25 de marzo de 2010 (puntuación 2) funciona, excepto que los símbolos de redirección y '&' causan errores de sintaxis.

Creo que la mejor y más sencilla solución es la publicada por Sager el 8 de octubre de 2014 (puntuación 0). Desafortunadamente, tiene un error tipográfico: '"%a"' debería ser '"%a%"'.

Aquí hay un archivo por lotes basado en la respuesta de Sager. Los símbolos de redirección y '&' en la entrada no causan problemas. Los únicos problemas que pude encontrar fueron causados ​​por cadenas que contenían comillas dobles.

@echo off & setlocal enableextensions & echo.
set /p input=Enter a string:
SET "x=" & for /f "delims=0123456789" %%i in ("%input%") do set x=%%i
if defined x (echo Non-numeral: "%x:~0,1%") else (echo No non-numerals)
Mike D avatar Jul 06 '2016 11:07 Mike D