Periksa hanya input numerik dalam file batch

10

Pada baris perintah berbasis Windows NT (kebanyakan untuk XP atau lebih tinggi), apakah ada cara untuk memverifikasi jika switch yang disediakan hanya angka? Tergantung pada nomornya, saya ingin mengulang kode x beberapa kali

Luke Kanada
sumber
1
Secara pribadi, saya lebih suka metode dalam jawaban ini untuk: Pastikan pengguna memasukkan bilangan bulat . Gunakan prosesor perintah untuk melakukan semua pekerjaan itu. Anda dapat menyederhanakannya menjadi 2 x baris sebagai solusi minimal: 1 set /a NO_LINES=%~1.; 2 if %NO_LINES% NEQ %~1 goto ABORT.. Ketika keduanya sama - Variabel atau parameternya adalah numerik .
akan

Jawaban:

18

Diedit untuk memperbaiki regex sesuai komentar debham . Ternyata menambahkan spasi sebelum pipa setelah gema menambahkan spasi ke string pipa, yang merupakan pemecahan awal / akhir pencocokan garis sebelumnya. Regex dapat ditingkatkan lebih lanjut dengan membuang spasi putih di awal dan akhir.


Itu findstrperintahnya. Itu dapat mencari file dengan ekspresi reguler, seperti grepdi Linux. Itu juga dapat mencari input yang di-piped.

@echo off

set param=%1

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

if %errorlevel% equ 0 (
    echo Valid number
)

Penjelasan

Parameter yang digunakan diatur ke dalam paramvariabel. Namun, tidak ada yang menghentikan Anda menggunakan parameter secara langsung ( %1untuk parameter pertama).

findstrdigunakan untuk mencari input pipa dengan /rbendera untuk regex.

Pola:

  • ^ berarti awal baris.

  • [0-9]berarti digit. The *berarti sebelumnya diulang nol atau lebih kali. Jadi [0-9][0-9]*artinya satu digit, plus nol atau lebih digit. Dengan kata lain, setidaknya satu digit. Satu +atau beberapa kali sepertinya tidak didukung oleh findstr. Catatan yang [1-9]digunakan untuk digit pertama untuk melarang nol terkemuka - lihat komentar.

  • $ berarti end of line.


Sekarang, for for dalam batch untuk x jumlah kali ... jika x bukan angka yang valid, loop sebenarnya tidak berjalan sama sekali - itu hanya akan dilewati untuk baris berikutnya. Jadi tidak perlu memeriksa apakah input adalah angka yang valid!

@echo off

set param=%1

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

Loop dilakukan dengan menggunakan for /l, di mana (x,y,z)berarti mulai dari x, kenaikan yhingga ztercapai. Dan itu diatur %%ake nomor / iterasi saat ini.

Catatan: ini sebenarnya gagal jika ada nol di depan, menyebabkan pemroses perintah memperlakukannya sebagai angka oktal. Lihat jawaban dbenham untuk solusi yang lebih baik.

Bob
sumber
Penjelasan yang bagus! Dan mudah digunakan
Kanada Luke
1
Seperti yang tertulis, solusi ini akan gagal dengan parameter seperti "this 1 fails"FINDSTR harus melakukan pencocokan tepat. Seharusnya tidak melakukan pencocokan kata.
dbenham
@ Benham, terima kasih. Saya mencoba awal / akhir pencocokan baris sebelumnya, tetapi gagal karena gema melewati ruang ekstra. Diperbaiki sekarang
Bob
@CanadianLuke Anda mungkin ingin melihat hasil edit.
Bob
Nilai 09atau 010dapat menyebabkan masalah karena notasi oktal. Lihat jawaban saya untuk regex yang melarang notasi oktal.
dbenham
8

Berikut ini berfungsi dengan baik untuk saya. SET /a param=%1+0selalu kembali 0jika %1kosong atau tidak numerik. Kalau tidak, itu memberikan nomor yang diberikan.

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number
Andreas
sumber
4
Ini akan gagal jika parameter = 0. Juga akan memperlakukan parameter seperti "1 + 1" sebagai angka, yang dapat menyebabkan masalah, tergantung pada persyaratan.
dbenham
7

Ini akan mendeteksi jika parameter pertama adalah bilangan asli yang valid (bilangan non-negatif).

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

Jika Anda ingin membolehkan kutipan di sekitar angka, maka

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

Catatan - nol di depan tidak diizinkan karena bets memperlakukannya sebagai oktal, sehingga nilai seperti 09tidak valid, dan 010memiliki nilai 8.

dbenham
sumber
3

Terinspirasi oleh jawaban Bob yang luar biasa dengan tambahan berikut

  • Perbaiki logika tingkat kesalahan
  • Terapkan loop / sub DoWork yang berulang melalui angka dan lakukan aritmatika

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

Masalah dengan yang berikut ini adalah bahwa ia selalu mengembalikan 'Nomor valid' karena 'jika errorlevel 0' selalu benar karena fakta bahwa itu adalah perbandingan '> = 0', bukan perbandingan '== 0'.

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

$ 0,02 saya

KeyboardJockey
sumber
Ups ... perbaiki tingkat kesalahan saya juga. Perbandingan numerik langsung dan bukan kejatuhan otomatis.
Bob
2

Anda dapat memvalidasi variabel apa pun jika jumlahnya:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")
Krzysztof Gapski
sumber
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
sumber
2
Bisakah Anda menambahkan beberapa penjelasan juga?
slhck
0

Saya tidak tahu mengapa tetapi pada sistem saya findstrperintah tidak berfungsi. Level kesalahan tidak diubah pada pertandingan atau tidak sama sekali.

Saya memang datang dengan metode lain

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

Ini adalah game yang menggunakan fungsi ini.

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