如何在批处理文件中请求用户输入整数



我想在Windows上创建一个批处理文件,该文件只能让用户输入1-31之间的数字...我可以稍后在批处理文件中使用此数字...有可能吗?

我试过这个

set /P "month=Enter the month of the year : "
findstr /i %month% %file% | sort /+24

谢谢:)

@echo off
:try_again
set /P "month=Enter the month of the year : "
echo %month%|findstr /r "[^0-9]" && (
    echo enter a number
    goto :try_again
)
::clears the leading zeroes.
cmd /c exit /b %month%
set /a month=%errorlevel%
if %month% gtr 31  (
   echo enter a number between 1 and 31
   goto :try_again
)
if %month% lss 1 (
   echo enter a number between 1 and 31
   goto :try_again
)

嗯,这两个选项是完全不同的

  • 让用户输入任何内容;然后,检查输入是否是 1 到 12 之间的数字,如果不是,则重试输入。
  • 让用户只需输入一个介于 1 和 12 之间的数字。

下面的批处理文件实现了第二种方法:

@echo off
setlocal EnableDelayedExpansion
echo Precede numbers 1 and 2 by a zero
set /P "=Enter a month: " < NUL
choice /C 0123456789 > NUL
set /A "number=%errorlevel%-1"
if %number% gtr 1 echo %number% & goto continue
set /P "=%number%" < NUL
if %number% equ 0 (
   choice /C 12 > NUL
   set "digit2=!errorlevel!"
) else (
   choice /C 012 > NUL
   set /A "digit2=!errorlevel!-1"
)
echo %digit2%
set /A "number=number*10+digit2"
:continue
echo/
echo Number read: %number%

当我需要非零数字输入时,我使用的一种非常简单但有效的方法是以下代码(请注意,这会在之后验证用户输入):

:RETRY_RESET
rem /* Since zero is considered as invalid, preset variable to `0` to
rem    not keep the former value in case the user just presses ENTER;
rem    you could also define a non-zero default value here optionally: */
set /A NUMBER=0
:RETRY_REUSE
rem // Display prompt now:
set /P NUMBER="Please enter a positive number: "
rem /* Convert entry to a numeric value; everything up to the first
rem    numeral is converted to a numeric value, except leading SPACEs
rem    or TABs are ignored and signs `+` and `-` are recognised: */
set /A NUMBER+=0
rem /* Caution: numbers with leading `0` are converted to octal ones!
rem    since `8` and `9` are not valid octal numerals, entries with
rem    such figures and leading zeros are converted to `0`! */
rem // Verify entry:
if %NUMBER% EQU 0 goto :RETRY_RESET
rem // Do something with `%NUMBER%` at this point...
rem /* Afterwards you can jump to `:RETRY_RESET` to enter another number;
rem    alternatively, jump to `:RETRY_REUSE` to maintain the former entry
rem    in case the user just presses ENTER... */

对于您能想到的任何条目,这都不会失败,因为保存该值的变量NUMBER在通过 set /A NUMBER+=0 转换为真数之前永远不会扩展。

该脚本可正确识别+ -符号。忽略前导空格。除了所有这些之外,第一个非数字数字之前的所有内容都转换为数字;因此,例如,像 SPACE +15.75k 这样的条目被转换为 15,因为.不是数字。

这种方法的缺点是前导零可能会导致意外的结果,因为set /A用八进制来解释数字;例如,012被转换为(十进制)100809被转换为0,因为89不是有效的八进制数字。
不过,一个好的观点可能是十六进制数在以 0x 为前缀的情况下被正确识别;例如,0x18转换为24; 0xAS变成10(因为S不是十六进制。

执行

此任务的一种安全而简单的方法是将 Set /A 命令与 || 条件运算符结合使用,并在输入无效输入时返回:label

可以使用set /a对输入值执行许多测试,而不会以使代码容易受到代码注入影响的方式扩展变量内容。

举个例子:

@Echo off
 Call:ValidNum $RV 31
 Call:ValidNum "" "" 5
 Set $
Goto:Eof
:ValidNum [returnvar] [max] [min]
SETLOCAL
Set "sign=-1"
 :VNumIn
 %= ensure nul value =%
  Set "input="
 %= define max value =%
  2> nul Set /a "max=%~2" || Set "max=2147483647"
 %= define min value =%
  2> nul Set /a "min=%~3" || Set "min=1"

  Set /p "input=Enter a number GEQ %min% LEQ %max%: "
 %= Input Testing. input +/-         , input > min     , input < max   , Hex/Octal for comparison =%
  2>nul Set /a "1/(sign-(input>>31))","max/(input/min)","1/(max/input)","HexOct=input" || Goto:VNumIn
 %= compare assignments to block hex, octal and leading 0's =%
  If not "%Input%"=="%HexOct%" Goto:VNumIn
( %= return value in $Num if no arg 1, else return in Arg1 =%
 ENDLOCAL & Set "%~1=%input%" 2> nul || Set "$Num=%input%"
 Goto:Eof
)

以下脚本是输入期间限制字符/键和输入后验证字符/值的混合体。代码非常复杂,但它非常灵活且安全。是这样的:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here (`findstr` reg. expr.):
set "WHITE=[0-9]" & rem // (positive list, accepted characters)
set "BLACK=[^`^]" & rem // (negative list, rejected characters)
set "LENGTH=2"    & rem // (optional limit for length of entry)
rem // resolve length limit:
set /A LENGTH-=1
if %LENGTH% LSS 0 set "LENGTH="
rem // Retrieve back-space character:
for /F %%C in ('echo prompt $H ^| cmd') do set "BS=%%C"
:HOOK
rem // Display prompt:
echo(Please enter something:
set "ENTRY="
:LOOP
rem // Use `xcopy /W` to capture a single key stroke:
set "KEY="
for /F "delims=" %%K in ('2^> nul xcopy /L /W "%~f0" "%~f0"') do (
    if not defined KEY set "KEY=%%K"
)
set "KEY=%KEY:~-1%"
rem // Leave loop in case ENTER has been pressed:
if not defined KEY goto :NEXT
rem // Disallow `"` to avoid syntax errors (`if`, no del. exp.):
set "KEY=%KEY:"=%" & rem "
rem // Disallow `=` to avoid syntax errors (`set /P`):
if "%KEY%"=="=" set "KEY="
rem // Disallow `   ` (tabulator):
if "%KEY%"=="   " set "KEY="
rem // Optional additional filter (include):
if defined WHITE (
    (echo("%KEY%" | > nul findstr /R /C:"%BS%" /C:"%WHITE%") || (
        set "KEY="
    )
)
rem // Optional additional filter (exclude):
if defined BLACK (
    (echo("%KEY%" | > nul findstr /R /C:^""%BLACK%"^") || (
        set "KEY="
    )
)
rem // In general, display string equals pressed key:
set "DISPLAY=%KEY%"
rem // Avoid space in display text (ignored by `set /P`):
if "%KEY%"==" " set "DISPLAY=_%BS% "
rem // Force to clear preceding character upon back-space:
if "%KEY%"=="%BS%" (
    set "DISPLAY=%BS% %BS%"
    if defined ENTRY set "ENTRY=%ENTRY:~,-1%"
    set "KEY="
)
rem // Ignore any more character if length limit is reached:
set "TEST=%ENTRY%"
if defined LENGTH if defined ENTRY (
    call set "TEST=%%ENTRY:~,%LENGTH%%%"
)
if not "%TEST%"=="%ENTRY%" (
    set "KEY=" & set "DISPLAY="
)
set "ENTRY=%ENTRY%%KEY%"
rem // Show display text:
< nul set /P ="%DISPLAY%"
goto :LOOP
:NEXT
echo(
rem /* Verify the entry; for instance,
rem    check numeric value after removal of leading zeros: */
cmd /C exit %ENTRY%
set /A ENTRY=%ErrorLevel%
set /A ENTRY+=0 & rem // (conversion to true numeric value)
if %ENTRY% LEQ  0 goto :HOOK
if %ENTRY% GTR 12 goto :HOOK
rem // Do something with the entry (display):
echo(You entered this value:
< nul set /P ="%ENTRY%"
echo(
endlocal
exit /B

脚本的核心是xcopy /L /W命令,它只需一次击键(/W),并且不复制(/L)。其输出由 for /F 循环捕获以获取当前键或字符。为了显示< nul set /P,使用任何内容都不会发送到其提示符中,而是显示消息文本,与echo不同,消息文本不会由换行符终止。另请参阅代码中的注释(rem)。

可以在顶部的Define constants here块中配置脚本:

  • 变量 WHITEfindstr 命令定义一个正字符集,其中一个字符/键必须等于; 设置为空字符串以禁用此集合; 对于我们的情况,[0-9] 适合于它定义的仅接受数字;
  • 变量 BLACKfindstr 命令定义一个负字符集,其中一个字符/键不能等于;设置为空字符串以禁用此列表;由于已经定义了WHITE,因此不需要BLACK;括号[ ]中的第一个字符必须是插入符号^,以便真正拒绝给定的字符;如果 WHITE 和 CC_中的集合45 重叠,后者优先;
  • 变量 LENGTH 定义了条目的最大长度,因此如果提供了给定数量的字符,则不再接受; 您可以通过 &leftarrow;— 键删除最后一个字符; 由于我们需要一个两位数的数值,2是这里的选择值;

相关内容

  • 没有找到相关文章

最新更新