web-dev-qa-db-ja.com

DOSで変数をインクリメントする方法は?

私はこれを解決しようとして過去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でのみスクリプトを実行する必要があります。

何か案は?

36
shadowz1337

私はあなたが別の答えを見つけたことに気付きました-しかし、事実はあなたの元のコードはほぼ正しいが構文エラーのためでした。

コードには次の行が含まれていました

set /A COUNTER=%COUNTER%+1

動作する構文は単純です...

set /A COUNTER=COUNTER+1

SETコマンドの詳細については、 http://ss64.com/nt/set.html を参照してください。私は、FreeDOSを使用するオプションを持っていない他の人のために、この説明を追加したいと考えました。

61
Furr

実際、DOSのsetには、算術を許可するオプションがありません。ただし、巨大なルックアップテーブルを作成できます。

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
5
Joey

パーティーには少し遅れましたが、それは興味深い質問です。

数値をインクリメントするために、独自の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
3
jeb

コマンドラインから直接:

 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
2
Niente0

私は自分の解決策を見つけました。

ここからFreeDOSをダウンロードします。 http://chtaube.eu/computers/freedos/bootable-usb/

次に、Counter.exeファイル(基本的にCounter.txtファイルを生成し、呼び出されるたびに内部の数値をインクリメントします)を使用して、次のコマンドを使用して変数の値を割り当てることができます。

Set /P Variable =< Counter.txt

次に、以下を実行することで250サイクル実行したかどうかを確認できます。

if %variable%==250 echo PASS

ところで、FreeDOSはこのコマンドをサポートしていないため、Set/Aはまだ使用できませんが、少なくともSet/Pコマンドはサポートしています。

2
shadowz1337

私は以前の貢献者のおかげで答えを作りました。

カスタムcounter.exeの時間がないため、 FREEDOS用にsed をダウンロードしました。

そして、バッチコードは、ユーティリティsedで「wc -l」をエミュレートし、ループに従って次のようになります(「1」からn + 1までの実行をインクリメントするために使用します):

最初の行に「test.txt」というファイルを手動で作成することを忘れないでください


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

私はDOSを何十年も使用していませんでしたが、 古い答え と私の記憶に基づいて、次のように動作するはずです(フィードバックがありませんが、答えは受け入れられたので、動作するように):

@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からは知っていましたが、再び見つけるのに苦労しました)

1
Stephan

set /aを使用したシンプルなソリューション

@CLS
@break on
@echo off
@Echo Begin PING/TraceRT Test - Version 1.0    8/16/2019
@Echo.
@echo.
@Echo  If %%1=-1, then unlimited runs, otherwise run only '%1' times and end.
@Echo  If unlimited, use ctrl-break/Ctrl-C to stop
@echo.
@echo.
if "%1"=="" goto end
set /A COUNTER=0

set /a START=COUNTER+1
ECHO                                     The total Runs so far is :  "-  %START%  -"

@Echo Logging Started >> ping-cap.txt
:Loop-Unlimited
IF "%COUNTER%"=="%1" GOTO END
set /A COUNTER=COUNTER+1
@time /T >> ping-cap.txt
@date /T >> ping-cap.txt
@ping charter.com >> ping-cap.txt
@tracert charter.com >> ping-cap.txt
@echo                                                                                    Loop Count is:  %COUNTER% >> ping-cap.txt

ECHO                                                                                    The total Runs so far is :  "-  %COUNTER%  -" 
GOTO Loop-Unlimited
goto end
:end
echo ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ   Ending test   ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

パーティーに来るのは非常に遅いですが、DOSバッチファイルの私の古い記憶から、各ループの文字列に文字を追加し続け、その文字の多くの文字列を探します。 250回の繰り返しの場合、非常に長い「サイクル」文字列があるか、10にカウントする変数のセットを使用して1つのループがあり、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
0
GadgetGuy