ตรวจสอบเฉพาะอินพุตตัวเลขในไฟล์แบตช์


10

ในบรรทัดคำสั่งที่ใช้ Windows NT (ส่วนใหญ่เป็น XP หรือสูงกว่า) มีวิธีการตรวจสอบหรือไม่ว่าสวิตช์ที่ระบุนั้นเป็นตัวเลขเท่านั้นหรือไม่ ขึ้นอยู่กับจำนวนฉันต้องการวนซ้ำรหัสxจำนวนครั้ง


1
ส่วนตัวผมชอบวิธีการในคำตอบนี้: ตรวจสอบให้แน่ใจผู้ใช้ป้อนจำนวนเต็ม ใช้หน่วยประมวลผลคำสั่งที่จะทำทุกงานที่ คุณสามารถทำให้มันง่ายขึ้นเป็น 2 x บรรทัดเป็นวิธีแก้ปัญหาที่น้อยที่สุด: 1. set /a NO_LINES=%~1; 2. if %NO_LINES% NEQ %~1 goto ABORT. ตอนที่สองมีค่าเท่ากัน - ตัวแปรหรือพารามิเตอร์เป็นตัวเลข
จะ

คำตอบ:


17

แก้ไขการแก้ไข regex ตามความคิดเห็นของ debham ปรากฎว่าการเพิ่มช่องว่างก่อนไปป์หลังจาก echo เพิ่มช่องว่างไปยังสตริง piped ซึ่งเป็นสิ่งที่ยากจนเริ่มต้น / สิ้นสุดของการจับคู่สายก่อนหน้านี้ Regex สามารถปรับปรุงให้ดีขึ้นได้โดยการยกเลิกช่องว่างที่จุดเริ่มต้นและจุดสิ้นสุด


มี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ใช้เพื่อค้นหาอินพุต piped ด้วย/rค่าสถานะสำหรับ regex

รูปแบบ:

  • ^ หมายถึงจุดเริ่มต้นของบรรทัด

  • [0-9]หมายถึงหลัก *หมายถึงก่อนหน้านี้ซ้ำแล้วซ้ำอีกเป็นศูนย์หรือมากกว่าครั้ง ดังนั้น[0-9][0-9]*หมายถึงหนึ่งหลักบวกศูนย์หรือมากกว่าหลัก กล่าวอีกนัยหนึ่งอย่างน้อยหนึ่งหลัก หนึ่งครั้งหรือมากกว่าดูเหมือนจะไม่ได้รับการสนับสนุนโดย+ findstrโปรดทราบว่า[1-9]ใช้สำหรับตัวเลขตัวแรกที่ไม่อนุญาตให้นำเลขศูนย์ - ดูความคิดเห็น

  • $ หมายถึงจุดสิ้นสุดของบรรทัด


ทีนี้, a สำหรับลูปในแบทช์สำหรับ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เป็นหมายเลขปัจจุบัน / การวนซ้ำ

หมายเหตุ: สิ่งนี้ล้มเหลวจริง ๆ ถ้ามีศูนย์นำหน้าทำให้ตัวประมวลผลคำสั่งให้ถือว่าเป็นเลขฐานแปด ดูคำตอบของ dbenhamสำหรับวิธีแก้ปัญหาที่ดีกว่า


คำอธิบายที่ยอดเยี่ยม! และใช้งานง่าย
Canadian Luke

1
ดังที่เขียนไว้วิธีแก้ปัญหานี้จะล้มเหลวโดยมีพารามิเตอร์เช่น"this 1 fails"The FINDSTR ควรจับคู่แบบตรงกันทุกประการ ไม่ควรจับคู่คำ
dbenham

@ dbenham ขอบคุณ ฉันพยายามเริ่มต้น / สิ้นสุดการจับคู่บรรทัดก่อนหน้านี้ แต่ไม่สำเร็จเนื่องจากเสียงสะท้อนผ่านพื้นที่พิเศษ แก้ไขแล้ว
Bob

@CanadianLuke คุณอาจต้องการดูการแก้ไข
Bob

ค่าของ09หรือ010อาจทำให้เกิดปัญหาเนื่องจากสัญกรณ์แปด ดูคำตอบของฉันสำหรับ regex ที่ไม่อนุญาตให้แสดงแปด
dbenham

8

ต่อไปนี้ใช้งานได้ดีมากสำหรับฉัน SET /a param=%1+0ผลตอบแทนเสมอ0ถ้า%1ว่างเปล่าหรือไม่เป็นตัวเลข มิฉะนั้นจะให้หมายเลขที่กำหนด

SET /a param=%1+0
IF NOT %param%==0 ECHO Valid number

3
สิ่งนี้จะล้มเหลวหากพารามิเตอร์ = 0 จะใช้พารามิเตอร์เช่น "1 + 1" เป็นตัวเลขซึ่งอาจทำให้เกิดปัญหาขึ้นอยู่กับข้อกำหนด
dbenham

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
)

หมายเหตุ - เลขศูนย์นำหน้าไม่ได้รับอนุญาตเนื่องจากแบทช์ถือว่าเป็นเลขฐานแปดดังนั้นค่าเช่น09นั้นไม่ถูกต้องและ010มีค่าเท่ากับ 8


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

ปัญหาต่อไปนี้คือมันจะส่งกลับ 'จำนวนที่ถูกต้อง' เสมอเพราะถ้า errorlevel 0 'เป็นจริงเสมอเนื่องจากมันเป็น'> = 0 'เปรียบเทียบไม่ใช่' == 0 'เปรียบเทียบ

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

$ .02 ของฉัน


อ๊ะ ... แก้ไขข้อผิดพลาดระดับบนของฉันด้วย การเปรียบเทียบโดยตรงกับตัวเลขมากกว่าการเลื่อนลงอัตโนมัติ
บ๊อบ

2

คุณสามารถตรวจสอบตัวแปรใด ๆ ได้ถ้าจำนวน:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.