2

一連のpingの平均遅延を決定するバッチを実行しているときに、異常な問題が発生しました。pingをFINDコマンドにパイプするときに、検索対象の文字列がpingで見つからない場合、FORループはDO部分を実行せず、代わりに次の反復にスキップします。

たとえば、次のコマンドを使用します。

FOR /F "tokens=*" %X in ('ping 8.8.8.8 -n 1 -w 1000^|FIND "Average"') do echo Result: %X

それをコマンドラインに投げると、期待どおりの結果が得られます。

Result: Minimum = 23ms, Maximum = 23ms, Average = 23ms

pingが失敗した場合、次のように表示されます。結果:

代わりに、結果はnullになります。そこにデッドIPを投げることでこれを試すことができます。

FOR /F "tokens=*" %X in ('ping 1.1.1.1 -n 1 -w 1000^|FIND "Average"') do echo Result: %X

コマンドがテキストファイルからIPアドレスを反復するバッチスクリプトでこれを使用すると、これは私にあらゆる種類の大混乱を引き起こします。

たとえば、{8.8.8.8,8.8.4.4,1.1.1.1}を含むip.txtがあります。バッチファイルがループで実行される場合、出力は次のようになると思います。

8.8.8.8 - 23ms
8.8.8.8 - 36ms
1.1.1.1 - 
8.8.8.8 - 20ms
8.8.8.8 - 18ms
1.1.1.1 - 

代わりに私は得る:

8.8.8.8 - 23ms
8.8.8.8 - 36ms
8.8.8.8 - 20ms
8.8.8.8 - 18ms

FINDが値なしで返す行は、DOフェーズを無視し、代わりにすぐに繰り返します。

FORループがDOフェーズを無視し、どのような状況でも反復を続けるのを見たことがありません。回避策や、なぜこれが起こっているのかについての説明さえも素晴らしいでしょう。

ありがとう!

編集1:ハリー・ジョンストン

早速のお返事ありがとうございます。残念ながら、私が知る限り、この問題はFORループの外では解決できません。

これは、単一のIPの例では正常に機能しますが、繰り返される複数の値では機能しません。問題は、レイアウトされているように、例ではすべての反復後に1行しか返さず、その行が最後の反復の値になることです。

これは、実行されている実際のコードにはるかに近いものです。テキストファイル名ip.txtを作成し、IPアドレスのリストを1行に1つずつ入力します。

test.bat

@echo off
cls
if not exist [logs] md [logs]
FOR /F "eol=;" %%i in (ip.txt) do for /f "tokens=9" %%p in ('ping %%i -n 3 -w 1000 ^|FIND "Average"') do echo Result - %%p 
pause

ip.txt

8.8.8.8
1.1.1.1
8.8.4.4

あなたのソリューションでは、これは[8.8.4.4]のpingの結果のみをエコーし​​ます。そのままでは、1番目と3番目の結果が返され、2番目のスキップが完了します。

EDIT2:dbenham

あなたたちは素晴らしいです、これは完璧にうまくいきました!問題の説明と回答の提供に時間を割いていただき、ありがとうございます:)

FOR /F "eol=;" %%i in (ip.txt) do for /f "tokens=9" %%p in ('ping %%i -n 3 -w 1000^|find "Average"^|^|echo . . . . . . . . ERROR') do echo Result: %%p
4

2 に答える 2

3

これは予想される動作です。DO句は出力行ごとに1回実行され、FINDコマンドは句に一致する行のみを出力するため、DO句は少なくとも1行が句に一致する場合にのみ実行されます。

あなたはこのようなことを試すことができます:

set result=No Response
FOR /F "tokens=*" %X in ('ping 1.1.1.1 -n 1 -w 1000^|FIND "Average"') do set result=%X
echo Result: %result%
于 2012-10-25T03:48:41.710 に答える
1

ハリー・ジョンストンは100%正しいです、あなたが見ている振る舞いは正確に期待通りです。無効なアドレスをPINGすると、FINDコマンドは出力を生成しないため、繰り返す必要はありません。

無効なアドレスが引き続き出力を生成するように、IN()句を変更する必要があります。私は2つの簡単な解決策を見ます:

1)FINDの代わりにFINDSTRを使用して、「平均」と「100%の損失」を検索します。トークンが9つを超える場合は、エラー状態です。このデモでは、スクリプトにIPアドレスを埋め込みました。

@echo off
for %%I in (8.8.8.8 1.1.1.1) do for /f "tokens=9,10" %%A in (
   'ping %%I -n 3 -w 1000^|findstr /c:"Average" /c:"100%% loss"'
) do if "%%B" neq "" (echo %%I  ERROR) else echo %%I  %%A

そしてここにいくつかのサンプル出力があります:

8.8.8.8  37ms
1.1.1.1  ERROR


2)||FINDが失敗した場合は、演算子を使用して条件付きで回線をエコーし​​ます

for %%I in (8.8.8.8 1.1.1.1) do for /f "tokens=9" %%A in (
    'ping %%I -n 3 -w 1000^|find "Average"^|^|echo . . . . . . . . ERROR'
) do echo %%I  %%A

出力は1番目のコードと同じです。


ハリーのソリューションを拡張してIPのリストをサポートすることも簡単です。内部ループの前に結果変数をリセットするだけです。

setlocal enableDelayedExpansion 
for %%I in (8.8.8.8 1.1.1.1) do (
  set "result=ERROR"
  for /f "tokens=9" %%A in (
      'ping %%I -n 3 -w 1000^|find "Average"'
  ) do set "result=%%A"
  echo %%I  !result!
)

繰り返しますが、出力は同じです。

于 2012-10-25T05:29:43.453 に答える