FIND命令返回空值

时间:2012-10-25 03:40:46

标签: windows batch-file null cmd

当运行一个确定一组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

2 个答案:

答案 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!
)

同样,输出是相同的。