web-dev-qa-db-ja.com

バッチファイルの入力検証-ユーザーが整数を入力したことを確認します

ユーザーが負ではない整数を入力する必要がある単純な操作を実行するために、Windowsバッチファイルを実験しています。ユーザー入力を取得するために、単純なバッチファイルテクニックを使用しています。

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

ユーザーはここに任意のテキストを入力できるので、ユーザーが入力したものが有効な番号であることを確認するルーチンを追加したいと思います。つまり、彼らは少なくとも1つの文字を入力し、すべての文字は0から9までの数字です。ルーチンの最後は、実際に有効な数値であるかどうかに基づいて異なるステートメントを実行するif/thenのようなものです。

ループや部分文字列などを試してみましたが、私の知識と理解はまだ薄いので...どんな助けもいただければ幸いです。

実行可能ファイルを作成することもできますが、バッチファイルよりも優れた方法があることはわかっていますが、少なくともこのタスクでは、バッチファイルを使用してそれをシンプルに保つようにしています。

13
Ben Brandt

皆さんありがとう。自分がループや文字列操作を見るのが難しくなるようにしようとしていた。数学の評価と比較に関するヒントを使用しました。これが、最終的にコンセプトスクリプトとして思いついたものです。

: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

このメソッドはすべての数値をキャッチし、それが正、負、またはゼロかどうかを検出できます。 10進数または文字列は非整数として検出されます。私が見つけた唯一のEdgeケースは、スペースを含む文字列です。たとえば、「数値1」というテキストは、ユーザー入力が数学として評価されたときにスクリプトをクラッシュ/クローズさせます。しかし、私の状況では、これは問題ありません。無効な入力でスクリプトを続行したくありません。

5
Ben Brandt

DOSバッチファイルではおそらくこれを行っていません。または、少なくとも、DOSでset /pをサポートするのは前代未聞です:-)

部分文字列を使用できます。実際、私は特定の通常言語用のパーサーを一度書いたことがありますが、面倒です。最も簡単な方法は、%userinput%を使用して、set /aの内容を別の変数に割り当てることです。結果が0と表示される場合は、入力自体が0であったかどうかを確認する必要があります。それ以外の場合は、数値ではないと結論付けることができます。

@echo off
setlocal enableextensions enabledelayedexpansion
set /p UserInput=Enter a number: 
set /a Test=UserInput
if !Test! EQU 0 (
  if !UserInput! EQU 0 (
    echo Number
  ) else (
    echo Not a number
  )
) else (
  echo Number
)

ただし、これはInt32の範囲の数値に対してのみ機能します。任意の数(おそらく浮動小数点数)だけを気にする場合は、ループベースのアプローチを使ってそれを分析する必要があります。

注:スペースの問題を解決するために更新されました。ただし、まだ潜んでいる問題があります。123/5はこれを評価できるため、set /aを入力すると「数値」が得られます...

15
Joey

これはヨハネスと同じ考えです。SET/ Aは数値を設定します。入力が数値でない場合は、0に変更します。これを利用して、チェックを行うことができます。

@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

別の方法として、小さなJavaScriptファイルを常に作成し、バッチファイルから呼び出すこともできます。 parseInt()を使用すると、入力を強制的に整数にすることも、独自の関数をロールして入力をテストすることもできます。

JavaScriptの記述はバッチファイルと同じくらい高速ですが、はるかに強力です。 IDEまたはコンパイラが必要です。メモ帳で実行できます。バッチファイルと同じように、すべてのウィンドウボックスで実行されます。それでは、なぜそれを利用しないのですか?

バッチファイルとJavaScriptを混在させることもできます。例:

sleep.jsの内容:

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

sleep.cmdの内容:

cscript /nologo sleep.js %1

これをバッチファイルから呼び出して、スクリプトを10秒間スリープさせることができます。単純なバッチファイルだけでは、そのようなことは困難です。

sleep 10

非常に単純なトリックを使用することもできます:

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

これは、findstrの正規表現一致機能を使用します。それほど印象的ではありませんが、時には役立ちます。

4
Joey

Ghostdog74が指摘したように、Joey Mar 26 '09(スコア10)およびWouter van Nifterick Mar 26 '09(スコア5)が投稿した回答は機能しません。

Joey Mar 25 '10(スコア2)によって投稿された回答は機能しますが、リダイレクト記号と '&'は構文エラーを引き起こします。

最良かつ最も簡単なソリューションは、Sager Oct 8 '14(スコア0)によって投稿されたものだと思います。残念ながら、タイプミスがあります: ‘"%a"’は ‘"%a%"’である必要があります。

これは、Sagerの回答に基づくバッチファイルです。入力のリダイレクト記号と「&」は問題を引き起こしません。私が見つけた唯一の問題は、二重引用符を含む文字列が原因でした。

@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)
2
Mike D

これも好きかもしれません-短くて簡単です。これは乗算トリックを使用してTestValを設定します。 TestValをUserInputと比較すると、すべての数値がゼロを含めて通過でき、非数値のみがelseステートメントをトリガーします。 ErrorLevelまたはその他の変数を設定して、失敗したエントリを示すこともできます。

@ECHO OFF
SET TestVal=0

SET /P UserInput=Please Enter a Number:
SET /A TestVal="%UserInput%"*1

If %TestVal%==%UserInput% (
   ECHO You entered the number %TestVal%
   ) else ECHO UserInput "%UserInput%" is not a number

GOTO EOF

:EOF
1
Whiskey Drainer

私はこれが古いことを知っていますが、私の解決策を共有するだけです。

set /p inp=Int Only : 
:: Check for multiple zeros eg : 00000 ::
set ch2=%inp%-0
if %inp% EQU 0 goto :pass
if [%inp%]==[] echo Missing value && goto :eof
if %inp:~0,1%==- echo No negative integers! && goto :eof
set /a chk=%inp%-10>nul
if %chk%==-10 echo Integers only! && goto :eof
:pass
echo You shall pass
:eof

テスト済みで、Windows 8で動作しています。

1
Flora

スペースがユーザー入力の一部であるときに発生するエラーに関する注釈に加えて。 errorlevel errorlevel = 9165を使用できます。文字列内のスペースまたは「no」入力のエラー処理に使用できます。

敬具、

エグバート

1
Egbert

あらゆる形式の入力に対してReadFormattedLineサブルーチンを使用できます。たとえば、次のコマンドは最大5桁の数字を読み取ります。

call :ReadFormattedLine UserInput="#####" /M "Please Enter a Number: "

このサブルーチンは純粋なバッチで記述されているため、追加のプログラムを必要とせず、パスワードの読み取りなど、いくつかのフォーマットされた入力操作が可能です。前の例では、サブルーチンは最大5桁の数値を読み取ります。 特定の形式で行を読み取る からReadFormattedLineサブルーチンをダウンロードできます。

0
Aacini
:ASK
SET /P number= Choose a number [1 or 2]: 
IF %number% EQU 1 GOTO ONE
IF %number% NEQ 1 (
  IF %number% EQU 2 GOTO TWO
  IF %number% NEQ 2 (
    CLS
    ECHO You need to choose a NUMBER: 1 OR 2.
    ECHO.
    GOTO ASK
  )
)

それは私にはうまくいきます。彼が以下の数値、文字列、浮動小数点数などを選択すると、メッセージ(「数値を選択する必要があります:1 OR 2.)」)が表示され、再度入力が要求されます。

0
Nerun

特定の質問に対して何らかのループとデフォルトの設定が必要な場合は、これが私の方法です。

内のコードに関するメモ。

@echo off
setlocal EnableDelayedExpansion
set "ans1_Def=2"

:Q1
set /p "ans1=Opt 1 of 1 [Value 1-5 / Default !ans1_Def!]: "

:: If not defined section. This will use the default once the ENTER key has been
:: pressed and then go to :Q2.
if not defined ans1 (
  echo/ & echo ENTER hit and the default used. Default is still: !ans1_Def! & echo/
  set "ans1=!ans1_Def!" && goto :Q2 )

:: This section will check the validity of the answer. The "^[1-5]$" will work
:: for only numbers between one and five in this example but this can be changed
:: to pretty much suit the majority of cases. This section will also undefine
:: the ans1 variable again so that hitting the ENTER key at the question
:: will work.
echo %ans1%|findstr /r /c:"^[1-5]$" >nul
if errorlevel 1 (
  echo/ & echo At errorlevel 1. Wrong format used. Default is still: !ans1_Def! & echo/
  set "ans1=" && goto Q1
  ) else ( echo Correct format has been used. %ans1% is the one. && goto :Q2 )

:Q2
echo/
echo -----------------------------
echo/
echo Now at the next question
echo !ans1!
echo/
pause
exit
0
Ste

変数が次の場合、変数を検証できます。

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

@echo off setlocal enableextensions enabledelayedexpansion set/p UserInput =数値を入力:set/a Test = UserInput if!Test! EQU 0(if!UserInput!EQU 0(echo Number)else(echo Not a number))else(echo Number)

なんでも素晴らしいですが、1つの小さなことを忘れています。0も数字です;(

0
user3367829

ホイールを再発明して、文字列の検証を行ういくつかの白い髪をバッチで成長させるか、vbscriptを使用できます

strInput = WScript.Arguments.Item(0)
If IsNumeric(strInput) Then
    WScript.Echo "1"
Else
    WScript.Echo "0"
End If

checkdigit.vbsとして保存し、バッチで

@echo off
for /F %%A in ('cscript //nologo checkdigit.vbs 100') do (
        echo %%A
        rem use if to check whether its 1 or 0 and carry on from here
)
0
ghostdog74

これはよりユーザーフレンドリーな方法です。

if %userinput%==0 (
cls
goto (put place here)
)
if %userinput%==1 (
cls
goto (put place here)
)
if %userinput%==2 (
cls
goto (put place here)
)
if %userinput%==3 (
cls
goto (put place here)
)
if %userinput%==4 (
cls
goto (put place here)
)
if %userinput%==5 (
cls
goto (put place here)
)if %userinput%==6 (
cls
goto (put place here)
)if %userinput%==7 (
cls
goto (put place here)
)
if %userinput%==8 (
cls
goto (put place here)
)
if %userinput%==9 (
cls
goto (put place here)
)

これは、あらゆるタイプのユーザー入力に使用できます。

0
Josh Heaps