0

FORループ内でプログラムを実行するときの遅延を計算するために、独自のコードを作成しました。弱点は、値 %time% が同時に評価されることです。そこでお聞きしたいのですが、(SET /A を使用して) 2 つの計算ブロックを別のサブルーチンに移動するようにコードを変更することは可能ですか。goto を使用してこのソリューションを Web で検索しましたが、ループに戻る方法がわかりません。私が見つけた例として、ファイルの終わりを参照してください。

@echo off 
Setlocal EnableDelayedExpansion

FOR /F "tokens=*" %%A IN ('DATE/T') DO FOR %%B IN (%%A) DO SET Today=%%B
ECHO It's %Today% today

CHCP 1250 > NUL

SET tpath=TEMP

for /f "delims=" %%x in (delimiter.ini) do set TAB=%%x

if not exist proxies.ini (
  echo Proxies not Found!
  pause 
exit
)

REM Set array of proxies
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=%time%
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg 
    SET t1=%time%
    REM FOR /F %%A IN ('TIME/T') DO SET t1=%%A

    echo !t0!
    SET /a s = !t0:~6,2!*100
    SET /a c = !t0:~9,2!
    SET /a c = "!c!-(!c!/10)*4"
    SET /a d1 = !s!+!c!
    echo !s!+!c! = !d1!
    echo !d1!

    echo !t1!
    SET /a s = !t1:~6,2!*100
    SET /a c = !t1:~9,2!
    SET /a c = "!c!-(!c!/10)*4"
    SET /a d2 = !s!+!c!
    echo !s!+!c! = !d2!
    SET /a delay = !d1!-!d2!   
    echo Delay:!delay!

   pause
   Echo Working proxy ... !proxy!     
  )
)


pause

編集 これは、dBenham がより優れたソリューションを投稿する前の 2 番目のテストです。

@echo off 
Setlocal EnableDelayedExpansion

FOR /F "tokens=*" %%A IN ('DATE/T') DO FOR %%B IN (%%A) DO SET Today=%%B
ECHO It's %Today% today

CHCP 1250 > NUL

SET tpath=TEMP

for /f "delims=" %%x in (delimiter.ini) do set TAB=%%x

if not exist proxies.ini (
  echo Proxies not found. 
  pause 
exit
)

REM Set array of proxies
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=!time!
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg 
    call :setTime !t0! !time!
    SET t1=!time!

:setTime
   Setlocal EnableDelayedExpansion
    SET t0=%1
    SET t1=%2
    echo !t0! !t1!
    pause
    SET /a m1 = !t0:~3,2!
    SET /a s1 = !t0:~6,2!
    SET /a s = !s1!*100
    SET /a c = !t0:~9,2!
    SET /a c = "!c!-((!c!/10)*4)"
    SET /a d1 = !s!+!c!
    echo !s!+!c! = !d1!
    echo !d1!

    echo !t1!
    SET /a m2 = !t1:~3,2!
    SET /a s2 = !t1:~6,2!
    if "!m2!" GTR "!m1!" (
      IF "!s2!" LSS "!s1!" (
          REM e.g. s1=20, s2=04 => 
          SET /a s2_cor = 60-!s1!+!s2!
          echo Correction: s2: !s2!
          SET /a s2_cor = "!s2!+60*(!m2!-!m1!)" 
      ) ELSE (
          SET /a s2_cor = "!s2!+60*(!m2!-!m1!-1)"
      )

      SET /a s2 = "!s2!+!s2_cor!"
    )

    SET /a s = !s2!*100    
    echo s2:!s2! , s:!s!    
    SET /a c = !t1:~9,2!
    SET /a c = "!c!-((!c!/10)*4)"
    SET /a d2 = !s!+!c!
    echo !s!+!c! = !d2!
    SET /a delay = !d2!-!d1!   
    echo Delay:!delay!
   pause
   endlocal
exit /b

   Echo Working proxy ... !proxy!     
  )
)

if NOT !asterisk!==1 (
 echo .
 echo Asterix not set
 echo .
 exit
)
pause
4

2 に答える 2

1

ジョーイはあなたの問題の 1 つを診断しました。しかし、経過時間の計算には多くの問題があります。

  • ジョーイが指摘したように、ループ内で遅延展開を使用する必要があります

  • Time2 から Time1 を減算する必要があります。あなたは反対のことをしています。

  • 小数秒の扱いは単に間違っています。

  • 経過時間が 1 分未満になると想定します。それは真実かもしれませんし、そうでないかもしれません。しかし、時間の秒の部分だけを見る必要があると誤って想定しています。T0=09:59:59.99 で T1=10:00:00.00 の場合はどうなるでしょうか? 正しい結果は 0.01 秒です。正しい結果を得る唯一の方法は、すべての時間コンポーネントを調べることです。値を計算する最も簡単な方法は、減算を行う前に、毎回午前 0 時を過ぎたセンチ秒数 (1/100 秒) に変換することです。

  • T0=23:59:59.99 で T1=00:00:00.00 の場合はどうなるでしょうか? 正しい結果は再び 0.01 秒になるはずです。ただし、両方の値をセンチ秒に変換してから T1 から T0 を引くと、負の数が得られます。トリックは、結果が負の場合、結果に 1 日 (24*60*60*100) を追加することです。これにより、この手法では、1 日のいつでも 24 時間未満の任意の時間間隔を計算できます。

  • SET /A は、0 で始まる数値を 8 進数として解釈します。そのため、コード内で 7 より大きい数値は正しく解釈されません。8 と 9 は有効な 8 進数ではないため、08 や 09 などのプラスの値はエラーを発生させます。以下のソリューションでは、いくつかの数学のトリックを使用して、各時刻コンポーネントの前に 1 桁を追加し、SET /A に 10 進表記を強制的に使用させ、最後に余分な時間を減算します。

その他の問題:

  • ほとんどの場合、SET /A を使用する場合、変数を展開する必要はありません。たとえば、数値変数に 1 を追加する場合は、単純set /A var=var+1に 、またはより簡潔にを使用できますset var+=1

  • あなたの FOR /F オプション"eol= tokens=1,2 delims=%TAB%"があなたが望むことをしているとは思いません。EOL オプションを無効にしようとしていると思われますが、実際には EOL を<space>文字に設定しています。これを無効にする適切な方法は、EOL を DELIM 値の 1 つに設定することです: "eol=%TAB% tokens=1,2 delims=%TAB%".

これは、いくつかの作業バッチ サブルーチンを使用して経過時間を計算するコードの関連セクションです。時間の計算を処理するために使用したアルゴリズムは、次のコードから派生しています: http://www.dostips.com/DtCodeFunctions.php#_Toc128586395

以下のコードには、高度なバッチ手法が多数含まれています。その多くが意味をなさない場合でも、気を悪くしないでください。ただし、サブルーチンを必要なスクリプトにコピーして、経過時間を簡単に計算できるはずです。

setlocal enableDelayedExpansion
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=!time!
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg
    SET t1=!time!

    call :diffTime t0 t1 Delay
    call :diffTime /f t0 t1 FormattedDelay
    echo Delay=!Delay!
    echo FormattedDelay=!FormattedDelay!

    pause
    Echo Working proxy ... !proxy!
  )
)
exit /b

:diffTime  [/F]  StartTimeVar  EndTimeVar  [ReturnVar]
::
:: Compute the elapsed time between the time values stored in
:: variables StartTimeVar and EndTimeVar. The value is returned
:: in units of centiseconds (1/100 second). If the /F option is
:: specified then the result is formatted as HH:MM:SS.DD
::
:: The result is returned in variable ReturnVar.
::
:: If ReturnVar is not specified then simply echo the result.
::
  setlocal enableDelayedExpansion
  set "diffTime.formatTime="
  if /i "%~1"=="/F" (
    set diffTime.formatTime=1
    shift /1
  )
  call :parseTime %1 diffTime.t1
  call :parseTime %2 diffTime.t2
  set /a "diff=diffTime.t2-diffTime.t1"
  if %diff% lss 0 set /a "diff+=24*60*60*100"
  if defined diffTime.formatTime (
    set /a "DD=diff, HH=DD/360000, DD-=HH*360000, MM=DD/6000, DD-=MM*6000, SS=DD/100, DD-=SS*100"%\n%
    if "!HH:~1!"=="" set "HH=0!HH!"
    if "!MM:~1!"=="" set "MM=0!MM!"
    if "!SS:~1!"=="" set "SS=0!SS!"
    if "!DD:~1!"=="" set "DD=0!DD!"
    set diff=!HH!:!MM!:!SS!.!DD!
  )
  endlocal & if "%~3"=="" (echo %diff%) else set "%~3=%diff%"
exit /b


:parseTime  TimeVar  ReturnVar
::
:: Parse the time value stored in TimeVar and compute the number of centiseconds (1/100 second) past midnight.
:: The result is returned in variable ReturnVar
::
  for /f "tokens=1-4 delims=:.," %%A in ("!%~1: =0!") do set /a "%~2=(((1%%A*60)+1%%B)*60+1%%C)*100+1%%D-36610100"
exit /b
于 2012-06-12T21:00:21.810 に答える
0

実際には遅延拡張を使用します。ループ内の!time!代わりに使用します。%time%同様に、ループ内で設定および使用する他のすべての変数についても同様です。

于 2012-06-12T18:25:12.590 に答える