我正在编写一个简单的批处理脚本来ping大量IP以查看它们是否在线。我写了一些代码,每次运行时都会出现错误
(此时出乎意料。
我不确定我哪里出错了。所以,如果有人能告诉我该怎么做,那就太好了。我是批处理的新手,所以我的代码不是最好的。
::@echo off
color b
title Get Online IPs
for /L %%A IN (0,1,255) do (
for /L %%B IN (0,1,255) do (
for /L %%C IN (0,1,255) do (
for /L %%D IN (0,1,255) do (
set %%A.%%B.%%C.%%D = IP
ping -n 1 %%A.%%B.%%C.%%D > ./iptemp.txt
for /F "delims=" %%i in (iptemp.txt) do set "iptemp=%%i"
if %iptemp% == "Packets: Sent = 1, Received = 0, Lost = 1 (100% loss)," (
echo IP offline
goto skip
)
echo %IP% >> IPlist.txt
echo %IP% is online!
:skip
)
)
)
)
答案 0 :(得分:0)
for /L %%A IN (0,1,255) do (
for /L %%B IN (0,1,255) do (
for /L %%C IN (0,1,255) do (
for /L %%D IN (0,1,255) do (
set "flag="
for /F "delims=" %%i in ('ping -n 1 %%A.%%B.%%C.%%D') do (
if "%%i" == "Packets: Sent = 1, Received = 0, Lost = 1 (100% loss)," set flag=Y
)
if defined flag (
echo %%A.%%B.%%C.%%D offline
) else (
echo %%A.%%B.%%C.%%D >> IPlist.txt
echo %%A.%%B.%%C.%%D is online!
)
)
)
)
)
{未经测试}
set %%A.%%B.%%C.%%D = IP
将环境变量0.0.0.0 Space .. 255.255.255.255 Space 设置为" 空间 IP&#34 ;
空格在标准=
语句中set
运算符的两个方面都很重要 - 您无法简单地反转语法并期望cmd
找出你的意思。
for /F "delims=" %%i in (iptemp.txt) do set "iptemp=%%i"
会将iptemp
的值设置为文件最后一行的内容。它不太可能匹配您在后面的测试中选择的字符串。
你不能在"块语句中使用标签" (带括号系列的陈述)
此外,正如在数千个SO响应中所解释的,为了访问块中变量的运行时值,您需要调用delayedexpansion
模式并使用!var!
。 (还有其他方法 - 这是最简单的方法)。 %var%
总是遇到阻止声明时变量的值
这是您的错误报告的来源 - 实际上"(此时非预期"。遇到阻止时,iptemp
未定义(并且该块是for /L %%A ...
块),cmd
将此行解释为
if == "Packets: Sent = 1, Received = 0, Lost = 1 (100% loss)," (
并且没有任何意义。
您的离线'报告会准确地说 - ' IP离线' - 不是IP地址。
修订后的(但未经测试的)代码使用flag
作为一袋土豆并将其初始化为 empty - 封闭的引号确保任何尾随空格都是分配给flag
for/f
依次将ping
输出的每一行的完整性提供给%%i
,然后将每一行(现在在%%i
中)与您的魔法进行比较字符串(请注意两个方面都需要引用)并且flag
设置为某些内容 - 如果魔术字符串匹配任何 em>输出线。
当for/f
完成后,flag
的当前值会被解释(请注意if defined
适用于当前值,而不是初始值),并生成一个或多个报告。
答案 1 :(得分:0)
我不明白为什么要ping整个IPv4地址范围,即ping全世界的所有IPv4地址。你知道你试图ping 4 294 967 296地址吗?
行set %%A.%%B.%%C.%%D = IP
完全错误。变量的名称和分配给变量的字符串值位于等号的错误一侧。然后查看Why is no string output with 'echo %var%' after using 'set var = text' on command line?,了解为什么等号周围不应有空格。
只要在以(
开头并以匹配)
结尾的命令块中定义或修改变量,并且在同一命令块中引用变量的值,就需要延迟环境变量扩展。在命令提示符窗口set /?
中运行并阅读所有输出帮助页面,以获取有关下面代码中使用的延迟扩展的详细信息。
Windows命令处理器不支持 FOR 循环中的标签。这里的解决方案是使用 IF 和 ELSE 。
IF 条件可能永远不会为真,因为相比较的是一个没有双引号的字符串和一个带双引号的字符串。此处需要使用周围的双引号进行字符串比较,但不会通过命令 IF 从比较的字符串中删除它们。
字符串比较的 IF 条件也是语法错误的原因,因为环境变量iptemp
未在第一个 FOR 之上定义,因此未定义解析命令块。这导致在大多数外部 FOR 首次执行之前已被替换为%iptemp%
,导致该行
if == "Packets: Sent = 1, Received = 0, Lost = 1 (100 loss)," (
这条线当然是完全错误的。注意:也会删除单个百分号。
要比较的字符串中的百分号必须使用一个百分号进行转义才能被解释为文字字符而不是变量引用的开头。
在最后 ECHO 行的下方代码中,必须使用^^
对感叹号进行转义,才能将其解释为文字字符,因为已启用延迟展开,这会改变!
的含义从简单的文字字符到变量名的分隔符,在解析命令块时应该引用其值而不进行扩展。
@echo off
setlocal EnableDelayedExpansion
color b
title Get Online IPs
set "ListFile=IPlist.txt"
if exist "%ListFile%" del "%ListFile%"
for /L %%A in (0,1,255) do (
for /L %%B in (0,1,255) do (
for /L %%C in (0,1,255) do (
for /L %%D in (0,1,255) do (
set "IP=%%A.%%B.%%C.%%D"
for /F "delims=" %%i in ('%SystemRoot%\System32\ping.exe -n 1 !IP!') do set "iptemp=%%i"
if "!iptemp!" == "Packets: Sent = 1, Received = 0, Lost = 1 (100%% loss)," (
echo !IP! is offline.
) else (
echo !IP! is online^^!>>"%ListFile%"
)
)
)
)
)
endlocal
在我的德语Windows上,字符串比较永远不会成立,因此所有IP都是" online"这当然是错的。
更好的方法是使用控制台应用程序的退出代码 PING ,成功ping时为0,错误时为1。可以使用if errorlevel X
if not errorlevel X
分别评估先前执行的命令或控制台应用程序的退出代码,具体取决于检查退出代码(错误级别)是否大于或等于X
或低于X
@echo off
setlocal EnableDelayedExpansion
color b
title Get Online IPs
set "ListFile=IPlist.txt"
if exist "%ListFile%" del "%ListFile%"
for /L %%A in (0,1,255) do (
for /L %%B in (0,1,255) do (
for /L %%C in (0,1,255) do (
for /L %%D in (0,1,255) do (
set "IP=%%A.%%B.%%C.%%D"
%SystemRoot%\System32\ping.exe -n 1 !IP! >nul
if errorlevel 1 (
echo !IP! is offline.
) else (
echo !IP! is online^^!>>"%ListFile%"
)
)
)
)
)
endlocal
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
color /?
del /?
echo /?
endlocal /?
for /?
if /?
ping /?
set /?
setlocal /?
title /?
另请阅读Microsoft文章: