Проверить только числовой ввод в пакетном файле

10

В командной строке на основе Windows NT (в основном для XP или выше) есть ли способ проверить, является ли предоставленный переключатель только числом? В зависимости от числа, я хочу, чтобы он перебрал код x количество раз

Канадский Люк
источник
1
Лично я предпочитаю метод в этом ответе для: Убедитесь, что пользователь ввел целое число . Используйте командный процессор, чтобы сделать всю эту работу. Вы можете упростить его до 2 х строк в качестве минимального решения: 1 set /a NO_LINES=%~1.; 2 if %NO_LINES% NEQ %~1 goto ABORT.. Когда два равны - переменная или параметр является числовым .
будет

Ответы:

18

Отредактировано, чтобы исправить регулярное выражение в соответствии с комментарием Debham . Оказывается, что добавление пробела перед каналом после эха добавляет пробел к переданной по конвейеру строке, что ранее нарушало совпадение начала / конца строки. Регулярное выражение может быть улучшено путем удаления пробелов в начале и в конце.


Там findstrкоманда. Он может искать файлы с регулярными выражениями, как grepв Linux. Он также может искать ввод по каналу.

@echo off

set param=%1

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

if %errorlevel% equ 0 (
    echo Valid number
)

объяснение

Используемый параметр устанавливается в paramпеременную. Однако ничто не мешает вам использовать параметр напрямую ( %1для первого параметра).

findstrиспользуется для поиска входных данных с /rфлагом regex.

Шаблон:

  • ^ означает начало строки.

  • [0-9]означает цифру. Эти *средства предыдущих повторяются ноль или более раз. Так [0-9][0-9]*означает одну цифру плюс ноль или более цифр. Другими словами, хотя бы одна цифра. В +один или несколько раз , кажется, не будет поддерживаться findstr. Обратите внимание, что [1-9]используется для первой цифры, чтобы запретить ведущие нули - см. Комментарии.

  • $ означает конец строки.


Теперь цикл for в пакете для x количество раз ... если x не является допустимым числом, цикл фактически вообще не запускается - он просто пропускается для следующей строки. Таким образом, нет необходимости проверять, является ли ввод действительным числом!

@echo off

set param=%1

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

Цикл завершается с использованием for /l, где (x,y,z)означает начало x, с шагом yдо zдостижения. И это устанавливает %%aтекущий номер / итерации.

Примечание: на самом деле происходит сбой, если есть начальный ноль, в результате чего командный процессор обрабатывает его как восьмеричное число. Смотрите ответ Дбенхэма для лучшего решения.

боб
источник
Отличное объяснение! И прост в использовании
канадец Люк
1
Как написано, это решение не будет работать с таким параметром, как "this 1 fails"FINDSTR должен выполнить точное совпадение. Это не должно делать совпадение слов.
Дбенхем
@dbenham Спасибо. Я пытался сопоставить начало / конец строки, но это не помогло из-за эхо-сигнала, передающего дополнительный пробел. Исправлено сейчас.
Боб
@CanadianLuke Вы можете взглянуть на редактирование.
Боб
Значение 09или 010может вызвать проблемы из-за восьмеричной записи. Смотрите мой ответ для регулярного выражения, которое запрещает восьмеричное обозначение.
dbenham
8

Следующее работает очень хорошо для меня. SET /a param=%1+0всегда возвращает значение, 0если %1оно пустое или не числовое. В противном случае он предоставляет данный номер.

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
Andreas
источник
4
Это не удастся, если параметр = 0. Также будет обрабатывать такой параметр, как «1 + 1», как число, что может вызвать проблемы, в зависимости от требований.
Дбенхем
7

Это обнаружит, является ли первый параметр действительным натуральным числом (неотрицательное целое число).

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

Если вы хотите разрешить кавычки вокруг числа, то

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

Примечание: начальные нули не допускаются, поскольку пакетный режим обрабатывает их как восьмеричные, поэтому значение like 09недопустимо и 010имеет значение 8.

dbenham
источник
3

Вдохновлен отличным ответом Боба со следующими дополнениями

  • Исправьте логику уровня ошибки
  • Реализуйте цикл / подпрограмму DoWork, который перебирает число и выполняет некоторую арифметику

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

Проблема со следующим заключается в том, что он всегда возвращает «Действительное число», потому что «если уровень ошибки 0» всегда истинен из-за того, что это сравнение «> = 0», а не «== 0».

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

мои $ .02

KeyboardJockey
источник
Упс ... исправил уровень ошибки на моем тоже. Прямое численное сравнение, а не автоматический провал.
Боб
2

Вы можете проверить любую переменную, если ее номер:

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
Можете ли вы добавить некоторые объяснения, пожалуйста?
Slhck
0

Я не знаю почему, но в моей системе findstrкоманда не работала. Уровень ошибки не изменялся во время матча или не совпадал.

Я придумала другой метод, хотя

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

Вот игра, которая использует эту функцию.

@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
источник