当运行一个确定一组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地址,这会给我带来各种各样的破坏。
例如,我有ip.txt,其中包含{8.8.8.8,8.8.4.4,1.1.1.1}。 当批处理文件在循环中运行时,我希望输出为:
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:Harry Johnston
感谢您的快速回复。不幸的是,问题无法在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] ping的结果。因为它会返回第一个和第三个结果,完成跳过第二个。
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
答案 0 :(得分: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%
答案 1 :(得分:1)
Harry Johnston 100%正确,您所看到的行为完全符合预期。当您PING一个无效的地址时,FIND命令不会产生任何输出,因此没有任何内容可以迭代!
您需要修改IN()子句,以便无效地址仍然产生输出。我看到了两个简单的解决方案:
1)使用FINDSTR而不是FIND并搜索" Average"并且" 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
输出与第一个代码相同。
为了支持IP列表,扩展Harry的解决方案也是微不足道的。只需在内循环之前重置结果变量。
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!
)
同样,输出是相同的。