バッチファイルで数値入力のみをチェックする


10

Windows NTベースのコマンドライン(主にXP以降)で、提供されているスイッチが数字のみであるかどうかを確認する方法はありますか?数に応じて、コードをx回ループする


1
個人的には、私はこの回答の方法を好みますユーザーが整数を入力したことを確認してください。コマンドプロセッサを使用して、すべての作業を行います。最小限の解決策として、2 x行に簡略化できますset /a NO_LINES=%~1。2 if %NO_LINES% NEQ %~1 goto ABORT。2つが等しい場合-変数またはパラメーターは数値です。
ます

回答:


18

デバムのコメントに従って、正規表現を修正するために編集されました。エコーの後にパイプの前にスペースを追加すると、パイプで連結された文字列にスペースが追加されることがわかりました。正規表現は、最初と最後の空白を破棄することでさらに改善できます。


findstrコマンドがあります。grepLinuxと同様に、正規表現でファイルを検索できます。パイプ入力を検索することもできます。

@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正規表現のフラグでパイプ入力を検索するために使用されます。

パターン:

  • ^ 行頭を意味します。

  • [0-9]数字を意味します。これ*は、前回の0回以上の繰り返しを意味します。つまり[0-9][0-9]*、1桁とゼロ以上の桁を意味します。つまり、少なくとも1桁。+1回以上でサポートされていないようです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は現在の数/反復に設定されます。

注:先行ゼロがある場合、これは実際には失敗し、コマンドプロセッサはこれを8進数として扱います。より良い解決策については、dbenhamの回答を参照してください。


素晴らしい説明!使いやすい
カナダのルーク

1
書かれているように、このソリューションは、"this 1 fails"FINDSTRが完全一致を実行する必要があるようなパラメーターで失敗します。単語の一致を行うべきではありません。
dbenham 2013

@dbenhamありがとう。前に行の開始/終了のマッチングを試しましたが、余分なスペースをエコーが通過するため失敗しました。今修正されました。
ボブ

@CanadianLuke編集内容を確認してください。
ボブ

09またはの値は010、8進表記のために問題を引き起こす可能性があります。8進数表記を許可しない正規表現については、私の回答を参照しください。
dbenham 2013

8

以下は私にとってとてもうまくいきます。が空または数値でない場合はSET /a param=%1+0常に戻ります。それ以外の場合は、指定された番号を提供します。0%1

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

4
これは、parameter = 0の場合は失敗します。また、「1 + 1」などのパラメータを数値として扱い、要件によっては問題を引き起こす可能性があります。
dbenham 2013

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
)

注-バッチでは8進数として扱われるため、先行ゼロは許可されません。したがって、などの値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^>

次の問題は、「== 0」の比較ではなく「> = 0」の比較であるため、「if errorlevel 0」が常にtrueであるため、常に「有効な数値」を返すことです。

@echo off

set param=%1

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

if errorlevel 0 (
    echo Valid number
)

私の$ .02


エラー:私のエラーレベルも修正しました。自動フォールスルーではなく直接数値比較。
Bobが

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.