我想重温昔日的怀旧之情。
我一直在测试一些批处理命令,但是我发现/a
在dos中不可用。
我是否可以使用另一种方法添加两个变量而不包含/a
?
@echo off
::this is how I would originally add two numbers
set /p number1=
set /p number2=
set /a "number1=number1+number2"
echo %number1%
pause >nul
exit
当我运行此程序时,dos状态为"invalid switch. - /a"
。
答案 0 :(得分:2)
与使用set /a
相比,它有些棘手,但是可以使用MS-DOS 6.22解决。
一部分是编写一个添加一位数字的函数,另一个编写可以添加多个位数的函数。
主要问题是将数字拆分为个位数,因为MS-DOS不支持字符串操作。
但这在FOR-Loop处理中存在一个微小的缺陷,/
将文本分为三部分。
for %%a in (`abcdef/ghijklmno`) do echo %%a
输出
abcdef g hijklmno
使用此技巧,可以将数字拆分为个位数
split.bat
@echo off
for %%P in (/%1.) do if %%P==: goto %1
set _idx=
set _remain=
set _splitRev=
set _splitRev_comma=
:loop
set _loop=1
for %%a in (/%_remain%) do call %0 :split %1 %%a
if NOT "%_remain%"=="" goto :loop
set %1=%_splitRev%
set %1_comma=%_splitRev_comma%
REM Clear temp vars
FOR %%v in (_remain _idx _loop _splitRev _splitRev_comma) do set %%v=
goto :eof
:split
if %_loop%%==2 goto :split_2
set _loop=2
set _remain=
set splitRev=%3%_splitRev%
set splitRev_comma=%3,%_splitRev_comma%
goto :eof
:split_2
set _remain=%3
goto :eof
:eof
add.bat 看起来像
@echo off
for %%P in (/%1.) do if %%P==: goto %1
call splitt _valueRev1 %1
call splitt _valueRev2 %2
set _result=
set _carry=
for %%d in(%_valueRev1_comma%,0,0,0,0,0) do call %0 :getDig1 %%d
REM Remove leading zeros
:zeroLoop
for %%z in (/%_result%) do set _remain=%%z
if not %_result%==0%_remain% goto :finish
set _result=%_remain%
goto :zeroLoop
:finish
echo %1+%2=%_result%
REM Clear temp vars
FOR %%v in (_result _carry _len _digit1 _digit2 _remain _valueRev1 _valueRev1_comma _valueRev2 _valueRev2_comma) do set %%v=
goto :eof
:getDig1
set _digit1=%2
set _digit2=
for %%d in (/%_valueRev2%0) do call %0 :getDig2 %%d
set _len=%_carry%
call %0 :lenAddDigit %_digit1%
call %0 :lenAddDigit %_digit1%
call %0 :len2val
set _result=%_val%%_result%
goto :eof
:getDig2if not "%_digit2%"==" set _valueRev2=%2
if "%_digit2%"=="" set _digit2=%2
goto :eof
:lenAddDigit
if %2==1 set _len=%_len%#
if %2==2 set _len=%_len%##
if %2==3 set _len=%_len%###
if %2==4 set _len=%_len%####
if %2==5 set _len=%_len%#####
if %2==6 set _len=%_len%######
if %2==7 set _len=%_len%#######
if %2==8 set _len=%_len%########
if %2==9 set _len=%_len%#########
goto :eof
:len2val
set _carry=
set _val=
if %_len%.==. set _val=0
if %_len%.==. goto :eof
if %_len%==# set _val=1
if %_len%==## set _val=2
if %_len%==### set _val=3
if %_len%==#### set _val=4
if %_len%==##### set _val=5
if %_len%==###### set _val=6
if %_len%==####### set _val=7
if %_len%==######## set _val=8
if %_len%==######### set _val=9
if NOT "%_val%"=="" goto :eof
set _carry=#
##########
if %_len%==########## set _val=0
if %_len%==########### set _val=1
if %_len%==############ set _val=2
if %_len%==############# set _val=3
if %_len%==############## set _val=4
if %_len%==############### set _val=5
if %_len%==################ set _val=6
if %_len%==################# set _val=7
if %_len%==################## set _val=8
if %_len%==################### set _val=9
goto :eof
:eof
在MS-DOS 6.22(VMWare)上成功测试
IF
不支持ELSE
解决方法:
IF %1==b echo It is equal
IF NOT %1==b echo It isn't equal
只有goto
可以跳到标签,CALL
只能开始另一个批次。
解决方法:
将类似的内容放入批处理的第一行
FOR %%P in (/%1) do IF %%P==: goto %1
...
REM This calls the current batch file and jumps to a label
CALL %0 :myLabel arg1
...
:myLabel
echo arg1=%2
echo Action1
echo Action2
goto :eof
没有代码块,例如
FOR %%a in (1 2 3 ) do (
set concat=%%a
echo %concat%
)
解决方法:
FOR %%a in (1 2 3 ) do CALL %0 :myFunc %%a
没有间接扩展变量
解决方法:
set var=content
set indirect=var
> temp$$$.bat echo set result=%%%indirect%%%
call temp$$$.bat
echo result=%result%
答案 1 :(得分:1)
如果您尝试从实际的DOS(而不是Windows从32位时代开始的Windows仿真)中执行此操作,则除非您手动处理输入中可能存在的每对数字(否则难以管理),否则根本不可能当您超过个位数时。
这始终是DOS批处理文件中的一个大缺陷,通常可以通过使用实际脚本语言(例如BASIC)调用小的脚本来补救,这些脚本通常由调用它们的同一.bat文件来写出。当然,这需要为您选择的语言配备翻译。
答案 2 :(得分:1)
这是我所能接近的。给定主脚本称为sum.bat
,请提供两个数字作为命令行参数。
这是sum.bat
的代码:
@echo off & > nul ver
rem // Define constants here:
set SUB=.\sum-sub.bat
set FILE=.\sum.tmp
set RESULT=.\sum-res.tmp
rem // Check if enough arguments are provided:
if "%2"=="" (>&2 echo ERROR: too few arguments!) & < nul find "" & goto :END
rem // Initialise variables:
set LIST=
rem // Create list of as many space-separated `#` symbols as given by 1st number:
call %SUB% %1
rem // Append list by as many space-separated `#` symbols as given by 2nd number:
call %SUB% %2
rem // Terminate execution in case of unsupported numbers:
if ErrorLevel 1 goto :END
rem // Create empty temporary file:
> nul copy /Y nul %FILE%
rem // Fill temporary file with as many bytes as list items are given:
for %%I in (%LIST%) do (> nul copy /B %FILE% + nul %FILE% /A)
rem // Get size of temporary file, filter out first summary line and store in file:
dir /A:-D /-W /-C %FILE% | find "1 File(s)" > %RESULT%
rem /* Read from file the summary line but display it without "1 File(s)" prefix;
rem since this is searched literally, the code becomes language-dependent;
rem the "bytes" suffix unfortunately remains: */
< %RESULT% (
for %%I in (# # # # # # # # # # # # # # # # # # # # # # # #) do > nul pause
sort & echo/
)
rem // Clean up temporary files:
del %FILE% %RESULT%
:END
这是子例程sum-sub.bat
的代码:
@echo off
rem // Jump to correct entry point to create/append a list with correct length:
2> nul goto :$%1 & < nul find "" & >&2 echo ERROR: unexpected argument!
rem // Do not add anything to the list upon errors:
goto :$0
rem /* Inverse list to add as many space-separated `#` symbols as given by the argument;
rem extend it in the same manner in order to support numbers greater than `12`: */
:$12
set LIST=%LIST% #
:$11
set LIST=%LIST% #
:$10
set LIST=%LIST% #
:$9
set LIST=%LIST% #
:$8
set LIST=%LIST% #
:$7
set LIST=%LIST% #
:$6
set LIST=%LIST% #
:$5
set LIST=%LIST% #
:$4
set LIST=%LIST% #
:$3
set LIST=%LIST% #
:$2
set LIST=%LIST% #
:$1
set LIST=%LIST% #
:$0
以下是一些用法示例:
>>> sum.bat 1 0 19 bytes >>> sum.bat 3 6 9 bytes >>> sum.bat 2 ERROR: to few arguments! >>> sum.bat 1 0 19 bytes >>> sum.bat 13 4 ERROR: unexpected argument!
我必须承认我在禁用了命令扩展名的Windows命令提示符中测试了这种方法,但在实际的MS-DOS环境中却没有。