【问题标题】:How to increment variable under DOS?如何在DOS下增加变量?
【发布时间】:2014-03-08 23:08:43
【问题描述】:

过去 3 小时我一直在尝试解决这个问题,但找不到解决方案。这是我的批处理脚本:

if NOT Exist Counter.txt GOTO START
Type c:\counter.txt
if %COUNTER% EQU %Cycles% goto Pass
if NOT %COUNTER% EQU %Cycles% goto Cycle

:START
Set COUNTER=0
set CYCLES=250

:Cycle
set /A COUNTER=%COUNTER%+1     <----------- PROBLEM
echo Iteration %COUNTER% of %CYCLES%
echo Delay 3 seconds to reboot
choice /cy /n /t:y,3
warmboot.com

:Pass
pause

它的作用是运行文件“warmboot.com”(它会重新启动我的 PC)并运行 250 个周期。一旦循环运行了 250 次(即当计数器等于循环数时),它就会停止。

在 Windows 下,这是可行的。但是,这在 DOS 环境下不起作用。我已经尝试了从 v4 一直到 v6.22 甚至 v7 的版本,当它到达“问题”行时它们都失败了。

如果我这样做:

set /A COUNTER=%COUNTER%+1
echo %Counter%

或者这个:

set /A COUNTER+=1
echo %Counter%

两者都将返回一个空行,即它不显示任何输出。

如果我输入:

set /?

然后它显示:

显示、设置或删除 cmd.exe 环境变量。

SET [变量=[字符串]]

variable 指定环境变量名。
string 指定一系列字符分配给变量。

但在 Windows 中的 CMD 下键入相同的命令会显示更多内容。我在想 DOS 下的 SET 函数不支持算术函数,但出于工作目的,我只能在 DOS 下运行我的脚本。

有什么想法吗?

【问题讨论】:

  • 漂亮确定普通 DOS 无法做到这一点。而是编写一个实际的程序(有很多语言可供选择,例如 Turbo PascalC,甚至可能是 QBasic)。
  • @Michael Madsen,我不熟悉这些语言,出于工作需要,我必须在 DOS 中运行批处理脚本。
  • 美好的旧时光...难道没有随 DOS 一起交付的 BASIC 吗?如果我没记错的话,它只有一个 EXE,而且很小(不到 1 MB?)
  • @shadowz1337:你的工作要求是否明确声明它必须是一个批处理脚本,或者只是它必须在DOS中运行?我提到的所有编译器/语言都在普通的 16 位 DOS 中运行,为了制作这样的程序,要学习的东西很少
  • 第 1 行和第 2 行将在 MSDos 中工作。第 3 行和第 4 行会给你语法错误。您确定您使用的是 MSDos?

标签: batch-file dos


【解决方案1】:

确实,旧 DOS 中的 set(而不是 Windows 的 cmd)没有允许算术的选项。 (cmd 确实有你描述的方式。)不过,你可以做一个巨大的查找表:

if %COUNTER%==249 set COUNTER=250
...
if %COUNTER%==3 set COUNTER=4
if %COUNTER%==2 set COUNTER=3
if %COUNTER%==1 set COUNTER=2
if %COUNTER%==0 set COUNTER=1

【讨论】:

  • 嗯,有没有更简单的方法? 250个循环只是一个例子,我实际上需要运行它超过3000次......
  • 我知道这已经过时了,但我只是按照这些思路做了一些事情,我应该提到正确的代码是 if %COUNTER%==1 ...
  • 应该有更优雅的方式
  • @K.Mulier:我们谈论的是 80 年代家庭用户操作系统中的 shell。批处理文件只适用于按顺序执行许多命令,而不是算术。
  • 嗨@Joey,你是对的。我很抱歉投反对票。只需将其转换为赞成票 ;-)
【解决方案2】:

这些似乎都不适合我:

@ECHO OFF

REM 1. Initialize our counter
SET /A "c=0"

REM Iterate through a dummy list. 
REM Notice how the counter is used: "CALL ECHO %%c%%" 
FOR /L %%i in (10,1,20) DO (

  REM 2. Increment counter
  SET /A "c+=1"

  REM 3. Print our counter "%c%" and some dummy data "%%i"
  CALL ECHO Line %%c%%: - Data: %%i
)

答案摘自:https://www.tutorialspoint.com/batch_script/batch_script_arrays.htm(部分:数组长度

结果:

Line 1: - Data: 10
Line 2: - Data: 11
Line 3: - Data: 12
Line 4: - Data: 13
Line 5: - Data: 14
Line 6: - Data: 15
Line 7: - Data: 16
Line 8: - Data: 17
Line 9: - Data: 18
Line 10: - Data: 19
Line 11: - Data: 20

【讨论】:

  • 问题是关于MS-DOS而不是Windows下的cmd.exe。所以你的解决方案行不通。过去没有FOR /L,也没有set /a
【解决方案3】:

很晚才参加聚会,但是根据我对 DOS 批处理文件的旧记忆,您可以在每个循环中不断向字符串中添加一个字符,然后查找包含那么多该字符的字符串。对于 250 次迭代,你要么有一个很长的“循环”字符串,要么你有一个循环内部使用一组变量计数为 10,然后另一个循环使用另一组变量计数为 25。

这是到 30 的基本循环:

@echo off
rem put how many dots you want to loop
set cycles=..............................
set cntr=
:LOOP
set cntr=%cntr%.
echo around we go again
if "%cycles%"=="%cntr%" goto done
goto loop
:DONE
echo around we went

【讨论】:

    【解决方案4】:

    直接从命令行:

     for /L %n in (1,1,100) do @echo %n
    

    使用批处理文件:

     @echo off
     for /L %%n in (1,1,100) do echo %%n
    

    显示:

     1
     2
     3
     ...
     100
    

    【讨论】:

    • 问题是关于MS-DOS而不是Windows下的cmd.exe。所以你的解决方案行不通
    【解决方案5】:

    我没有使用 DOS - puh - 感觉就像几十年一样,但根据 an old answer 和我的记忆,以下应该可以工作(虽然我没有得到反馈,但答案被接受了,所以它似乎工作):

    @echo off
      REM init.txt should already exist
      REM to create it:
      REM   COPY CON INIT.TXT
      REM   SET VARIABLE=^Z
      REM ( press Ctrl-Z to generate ^Z )
      REM
      REM also the file "temp.txt" should exist.
    REM add another "x" to a file:
    echo x>>count.txt
    REM count the lines in the file and put it in a tempfile:
    type count.txt|find /v /c "" >temp.txt
    
    REM join init.txt and temp.txt to varset.bat:
    copy init.txt+temp.txt varset.bat
    REM execute it to set %variable%:
    call varset.bat
    
    for %%i in (%variable%) do set numb=%%i
    echo Count is: %numb%
       REM just because I'm curious, does the following work? :
       set numb2=%variable%
       echo numb2 is now %var2%
    if %numb%==250 goto :finished
    echo another boot...
    warmboot.exe
    :finished
    echo that was the last one.
    

    在 DOS 中,set /aset /p 都不存在,所以我们必须解决这个问题。 我认为for %%i in (%variable%) do set numb=%%iset numb2=%variable% 都可以,但我无法验证。

    警告:由于 DOS 中没有 ">" 或 ":finished 标签处的批处理文件(因为它会继续递增,并且 251 不再等于 250)

    (PS:基本思路来自here。感谢foxidrive。我知道,我从StackOverflow知道但很难再找到它)

    【讨论】:

    • 有趣的解决方案,我测试了它并且它有效,但您应该将&gt;nul 添加到copy init.txt+temp.txt varset.bat 以避免复制文本。它也有点慢,因为对于更大的值,它会变得越来越慢。
    • @jeb 感谢您的反馈(我没有要测试的 DOS)。是的,它变慢了,但我认为只要涉及重新启动之类的事情,这并不重要。当计数器达到一万时,这也可能是一个 - 嗯 - 次优解决方案。
    【解决方案6】:

    聚会有点晚了,但这是一个有趣的问题。

    您可以编写自己的 inc.bat 来增加数字。
    它可以将数字从 0 递增到 9998。

    @echo off
    if "%1"==":inc" goto :increment
    
    call %0 :inc %counter0%
    set counter0=%_cnt%
    if %_overflow%==0 goto :exit 
    
    call %0 :inc %counter1%
    set counter1=%_cnt%
    if %_overflow%==0 goto :exit 
    
    call %0 :inc %counter2%
    set counter2=%_cnt%
    if %_overflow%==0 goto :exit 
    
    call %0 :inc %counter3%
    set counter3=%_cnt%
    goto :exit
    
    :increment
    set _overflow=0
    set _cnt=%2
    
    if "%_cnt%"=="" set _cnt=0
    
    if %_cnt%==9 goto :overflow
    if %_cnt%==8 set _cnt=9
    if %_cnt%==7 set _cnt=8
    if %_cnt%==6 set _cnt=7
    if %_cnt%==5 set _cnt=6
    if %_cnt%==4 set _cnt=5
    if %_cnt%==3 set _cnt=4
    if %_cnt%==2 set _cnt=3
    if %_cnt%==1 set _cnt=2
    if %_cnt%==0 set _cnt=1
    goto :exit
    
    :overflow
    set _cnt=0
    set _overflow=1
    goto :exit
    
    :exit
    set count=%counter3%%counter2%%counter1%%counter0%
    

    这里有一个使用示例

    @echo off
    set counter0=0
    set counter1=
    set counter2=
    set counter3=
    
    :loop
    call inc.bat
    echo %count%
    if not %count%==250 goto :loop
    

    【讨论】:

      【解决方案7】:

      感谢之前的贡献者,我构建了我的答案。

      没有时间自定义counter.exe,我下载了sed for FREEDOS

      然后批处理代码可以是,使用实用程序 sed 模拟“wc -l”,根据您的循环(我只是使用它来增加从“1”到 n+1 的执行):

      记得手动创建一个文件“test.txt”,第一行写上

      0


      sed -n '$=' test.txt > counter.txt
      set /P Var=< counter.txt
      echo 0 >> test.txt
      

      【讨论】:

        【解决方案8】:

        我知道您找到了另一个答案 - 但事实是您的原始代码几乎正确,但存在语法错误。

        您的代码包含该行

        set /A COUNTER=%COUNTER%+1
        

        并且可以使用的语法很简单......

        set /A COUNTER=COUNTER+1
        

        有关 SET 命令的所有详细信息,请参阅http://ss64.com/nt/set.html。我只是想为没有选择使用 FreeDOS 的其他人添加此说明。

        【讨论】:

        • 这个答案是错误的,因为这个问题明确地是关于纯 MS-DOS,而不是关于 cmd.exe。
        • 更错误的是,set /a var=%var%+1 工作正常(虽然不推荐)
        • @niico 因为此答案中的示例适用于当今大多数人实际使用的现代版本的 Windows。对于实际提出的问题,这不是正确答案,但对于想知道如何在现代版本的 Windows 上增加变量的人来说,这是正确答案。
        【解决方案9】:

        我找到了自己的解决方案。

        从这里下载 FreeDOS: http://chtaube.eu/computers/freedos/bootable-usb/

        然后使用我的 Counter.exe 文件(它基本上会生成一个 Counter.txt 文件并在每次调用它时递增其中的数字),我可以使用以下方法将数字的值分配给一个变量:

        Set /P Variable =< Counter.txt
        

        然后,我可以通过以下方式检查它是否已运行 250 个周期:

        if %variable%==250 echo PASS
        

        顺便说一句,我仍然不能使用 Set /A,因为 FreeDOS 不支持此命令,但至少它支持 Set /P 命令。

        【讨论】:

          猜你喜欢
          • 2011-02-24
          • 1970-01-01
          • 1970-01-01
          • 2020-02-26
          • 2017-07-03
          • 2015-09-21
          • 2011-06-03
          • 2019-09-03
          • 1970-01-01
          相关资源
          最近更新 更多