我想在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
被转换为(十进制)10
,08
和09
被转换为0
,因为8
和9
不是有效的八进制数字。
不过,一个好的观点可能是十六进制数在以 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
块中配置脚本:
- 变量
WHITE
为findstr
命令定义一个正字符集,其中一个字符/键必须等于; 设置为空字符串以禁用此集合; 对于我们的情况,[0-9]
适合于它定义的仅接受数字; - 变量
BLACK
为findstr
命令定义一个负字符集,其中一个字符/键不能等于;设置为空字符串以禁用此列表;由于已经定义了WHITE
,因此不需要BLACK
;括号[
]
中的第一个字符必须是插入符号^
,以便真正拒绝给定的字符;如果WHITE
和 CC_中的集合45 重叠,后者优先; - 变量
LENGTH
定义了条目的最大长度,因此如果提供了给定数量的字符,则不再接受; 您可以通过 ←— 键删除最后一个字符; 由于我们需要一个两位数的数值,2
是这里的选择值;