2012-10-25 266 views
2

當運行確定一組ping的平均延遲的批處理時,我遇到了一個不尋常的問題。當ping到FIND命令時,如果在ping中沒有找到正在搜索的字符串,FOR循環不執行DO部分,而是跳到下一次迭代。如果你折騰到這一個命令行,你會得到預期的結果FIND命令返回空值

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 

對於失敗的平,我希望看到: 結果:

結果爲空。你可以通過在那裏扔掉一個死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階段,並在任何情況下繼續迭代。任何變通辦法或甚至只是解釋爲什麼會發生這種情況都是美妙的。

謝謝!

EDIT1:哈里·約翰斯頓

感謝您的快速回復。不幸的是,這個問題無法在FOR循環之外解決,就我所知。

這適用於單個IP示例,但不適用於正在迭代的多個值。問題是,正如所示,您的示例將只會在所有迭代之後返回一行,並且該行將是最後一次迭代的值。

這更接近正在運行的實際代碼。創建一個文本文件名稱ip.txt,並填寫一個IP地址列表,每行一個。

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]的平的結果。因爲它會返回第一個和第三個結果,完成第二個跳過。

編輯2: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 

回答

1

哈利·約翰斯頓是100%正確的,你所看到的行爲是完全符合市場預期。當你PING一個無效的地址FIND命令不會產生任何輸出,所以沒有什麼可迭代的!

您需要修改IN()子句,以便無效地址仍然生成輸出。我看到2個簡單的解決方案:

1)使用FINDSTR而不是FIND並搜索「Average」和「100%loss」。如果有超過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 

的輸出是相同第一個代碼。


延長Harry的解決方案以支持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! 
) 

再次,輸出是相同的。

+0

謝謝!整個情況現在更有意義。我的第一次嘗試是使用第二種方法,我沒有想到在ERROR返回之前擴展8個分隔符。我剛剛趕上沒有這些分隔符的結果是NULL。 – Xestrix

3

這是預期的行爲。 DO子句對每行輸出執行一次,而FIND命令只輸出與子句匹配的行,所以只有至少有一行符合子句纔會執行DO子句。

你可以嘗試這樣的事:

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% 
+0

感謝您的建議,我編輯了這個問題來說明爲什麼這不能解決問題。 – Xestrix