如何解决将txt文件中的行批量读取到变量中
我正在尝试找出如何从名为“ IPList.txt)的文件中将IP地址读取到批处理脚本中的各个变量中。
:DEFinitioNS
set LOGFILE=IPScript.log
set IPLIST=C:\IPLIST.txt
echo Script Started >> %LOGFILE%
goto SetIP
:SetIP
for /f "tokens=*" %%a in (%IPLIST%) do (
set FirstIP=%%a
)
echo The first IP is %FirstIP% >> %LOGFILE%
exit
我在“ IPscript.log”中得到的输出是“第一个IP是:”,没有列出IP,只是一个空格。另外,我是否可以在一个for循环中设置这样的多个IP?
解决方法
这是一个可以帮助您的简单示例:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
:DEFINE_LOCAL_VARIABLES
Set "IPLIST=C:\IPLIST.txt"
Set "LOGFILE=IPScript.log"
:CHECK_SOURCE_EXISTS
For %%G In ("%IPLIST%") Do If "%%~aG" Lss "-" (
Echo The file %IPLIST% does not exist.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
) Else If "%%~aG" GEq "d" (
Echo Expected a file,but %IPLIST% is a directory.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
)
:UNDEFINE_LOCAL_VARIABLES
For /F "Delims==" %%G In ('"(Set IP[) 2> NUL"') Do Set "%%G="
:START_MAIN
Set "i=1000"
(
Echo Script Started
For /F UseBackQ^ Delims^=^ EOL^= %%G In ("%IPLIST%") Do (
Set /A i += 1
SetLocal EnableDelayedExpansion
For %%H In ("!i:~-3!") Do (
EndLocal
Set "IP[%%~H]=%%G"
Echo IP[%%~H] is %%G
)
)
) 1> "%LOGFILE%"
:CHECK_IP_VARIABLES_EXIST
If Not Defined IP[001] (
Echo %IPLIST% had no readable file content.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
)
:VIEW_IP_VARIABLES
Set IP[
Pause & GoTo :EOF
如果您有一个现有的%LOGFILE%
,并打算将其追加到其他位置(而不是覆盖/创建一个),请将1> "%LOGFILE%"
更改为1>> "%LOGFILE%"
。
如果您真的不需要%LOGFILE%
,请例如它只是被您用于测试,看起来会像这样:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
:DEFINE_LOCAL_VARIABLES
Set "IPLIST=C:\IPLIST.txt"
:CHECK_SOURCE_EXISTS
For %%G In ("%IPLIST%") Do If "%%~aG" Lss "-" (
Echo The file %IPLIST% does not exist.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
) Else If "%%~aG" GEq "d" (
Echo Expected a file,but %IPLIST% is a directory.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
)
:UNDEFINE_LOCAL_VARIABLES
For /F "Delims==" %%G In ('"(Set IP[) 2> NUL"') Do Set "%%G="
:START_MAIN
Set "i=1000"
Echo Script Started
For /F UseBackQ^ Delims^=^ EOL^= %%G In ("%IPLIST%") Do (
Set /A i += 1
SetLocal EnableDelayedExpansion
For %%H In ("!i:~-3!") Do (
EndLocal
Set "IP[%%~H]=%%G"
)
)
:CHECK_IP_VARIABLES_EXIST
If Not Defined IP[001] (
Echo %IPLIST% had no readable file content.
Echo Press any key to end this script.
Pause 1> NUL
GoTo :EOF
)
:VIEW_IP_VARIABLES
Set IP[
Pause & GoTo :EOF
两个示例中的最后一行都是出于显示目的。如果您正在cmd.exe
中测试/运行此脚本,则可以忽略它。
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" "%filename1%"') DO set "IP%%a=%%b"
)
set IP
findstr
读取filename1
中的文件,并产生格式为n:content of line n
的列表。
for /f
读取此列表,并使用2个标记对其进行分区-%%a
使用{{1获得第一个标记(1),其余{* 1}}行(*) }}作为分隔符。
因此,只需从此处设置%%b
变量即可。
:
显示以IP
开头的所有变量
可能性是您的文件在最后一个IP之后包含空行。您的原始代码本来会报告 LAST IP,而不是 FIRST ,因为set ip
中的值在每次迭代时都会被覆盖,因此可以通过将其设置来清除读取空行后什么都不会。
在这种情况下,上面的解决方案将简单地执行(例如)ip
,清除变量。
您可能已经通过使用获得了第一个IP
firstip
我在这里假设一个干净的环境-也就是说,您运行的每个批处理在set "IP6="
之后都包含一个if not defined firstip set "FirstIP=%%a"
(当批处理完成时将还原初始环境),并且使用的变量是已知为空。
奖金:
将setlocal
命令更改为
@echo off
将set
设置为最后一个非空行的编号,因为set "IP%%a=%%b"&if "%%b" neq "" set "ipmax=%%a"
为空代表空行。
批处理文件可能具有以下命令行:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LOGFILE=%~dp0IPScript.log"
set "IPLIST=%~dp0IPLIST.txt"
set "AddressCount=0"
echo Script started>"%LOGFILE%"
for /F "delims==" %%I in ('set IP_Address_ 2^>nul') do set "%%I="
if exist "%IPLIST%" for /F "useback delims=" %%I in ("%IPLIST%") do (
set /A AddressCount+=1
call set "IP_Address_%%AddressCount%%=%%I"
)
if not %AddressCount% == 0 (
if %AddressCount% == 1 (
echo The IP address is:
) else echo The IP addresses are:
echo/
set IP_Address_
) >>"%LOGFILE%"
endlocal
批处理文件的前两个命令行定义了执行环境,这意味着:
- 禁用命令回显模式。
- 将当前命令扩展状态推送到堆栈上并启用命令扩展。
- 将当前延迟扩展状态推送到堆栈上,并禁用延迟的环境变量扩展。
- 将当前目录推送到堆栈上。
- 将指针推到堆栈上当前环境变量列表,并创建整个当前环境变量列表的副本以供下一步使用。
第三行和第四行定义两个环境变量,它们的名称是日志文件的名称,而IP地址列表文件的名称是完整的限定文件名。这两个文件的文件路径都定义为包含用%~dp0
引用的批处理文件的目录的路径。该路径始终以\
结尾,因此,在将此路径与两个文件名连接时,不需要其他反斜杠。
第五行定义值为AddressCount
的环境变量0
。
第六行在当前目录中创建日志文件,并覆盖一个已经存在的日志文件。重定向操作符>
没有剩余空间,因为该空间将由命令 ECHO 输出,因此也作为尾随空间写入了日志文件。
带有选项/F
的第一个 FOR 命令在后台以%ComSpec% /c
开始,另外一个命令过程是将'
之间的命令行附加为附加参数。在Windows安装到C:\Windows
中的情况下,这样执行是在后台执行的:
C:\Windows\System32\cmd.exe /c set IP_Address_ 2>nul
Windows为在后台启动的命令进程创建当前环境变量列表的副本。后台命令过程运行命令 SET 来输出所有具有名称,等号和名称以IP_Address_
开头的变量的字符串值的环境值。用于处理后台命令进程的 STDOUT 的输出分别由 FOR 捕获,该命令进程正在处理批处理文件。由 SET 输出的错误消息在没有定义以IP_Address_
开头的环境变量的情况下输出,从句柄 STDERR 重定向到设备 NUL 禁止显示此错误消息。
阅读有关Using command redirection operators的Microsoft文档,以获取2>nul
的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>
必须在 FOR 命令行上使用脱字符号^
进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式dir
命令行。
FOR 在启动命令 SET 后,启动的后台命令进程自身关闭后,逐行处理捕获的输出。空行总是被 FOR 忽略,由于 SET 没有空行输出,因此可以忽略。
FOR 默认情况下会使用常规空格和水平制表符作为分隔符将当前行拆分为子字符串。这里不需要这种默认的行拆分行为。选项delims==
将等号定义为字符串定界符,以分隔=
上的行,该行是变量名和变量值之间的字符。
FOR 接下来将忽略该行。命令 SET 仅输出以IP_Address_
开头的行,因此在这种情况下可以保留默认的eol=;
。
FOR 仅将第一个子字符串分配给指定的循环变量I
,因为默认情况下tokens=1
。在这种情况下,这正是想要的行为。
因此 FOR 为循环变量IP_Address_
分配了一个以I
开头的环境变量名称,然后运行命令 SET 删除此环境变量在当前处理批处理文件的命令过程的环境变量列表中。
换句话说,第一个 FOR 用于删除所有在批处理文件外部偶然定义的名称以IP_Address_
开头的环境变量。
下一行首先检查批处理文件目录中是否完全包含带有环境变量列表的文件。在这种情况下,再次使用 FOR 处理行,但这一次是从指定的列表文件逐行读取而不是捕获后台命令进程的输出。将"
而不是'
与选项usebackq
一起使用会有所不同。
使用选项delims=
定义了一个空的定界符列表,从而导致每个非空行都不以;
开头,而完全没有分配给指定的循环变量I
。 / p>
对于每个分配给循环变量I
的字符串,环境变量AddressCount
的当前值使用由命令 SET 计算的算术表达式加1。
此值在下一个命令行上使用,以定义名称以IP_Address_
开头的环境变量,并将当前地址计数值附加到从分配给该环境变量的文件读取的行中。
通常将delayed expansion用于此类任务,第二个 FOR 循环的命令块中的第二个命令行将是:
set "IP_Address_!AddressCount!=%%I"
但是上面的代码使用了命令call
的另一种方法来第二次解析set "IP_Address_%%AddressCount%%=%%I"
,而在 IF 条件出现之前,它已经修改为set "IP_Address_%AddressCount%=%I"
完全执行了 FOR 。
下一个 IF 条件检查是否从具有IP地址的列表文件中读取了任何行。在这种情况下,首先要输出一条信息行,具体取决于已从文件中准确读取了一行或多于一行。然后,输出一个空行,最后所有名称以IP_Address_
开头的环境变量都以=
开头,并将行(IP地址)分配给该环境变量。所有这些输出都将添加到日志文件中。
最后一条命令恢复以前的执行环境,这意味着:
- 丢弃当前环境变量列表,并从堆栈中弹出指向环境变量初始列表的指针,从而恢复环境变量的初始列表。换句话说,在第二个命令行中的命令 SETLOCAL 之后,由批处理文件定义或修改的所有环境变量将永远丢失。
- 从堆栈中弹出当前目录的路径,然后将该目录再次设为当前目录。
setlocal
和endlocal
之间的当前目录没有被它们之间的代码更改,因此这里无关紧要。 - 从堆栈中弹出延迟扩展状态,并相应地启用或禁用延迟环境变量扩展,以恢复初始延迟扩展行为。
- 从堆栈中弹出当前命令扩展状态,并相应地启用或禁用命令扩展以恢复初始命令扩展行为。
要了解所使用的命令及其工作方式,请打开command prompt窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
-
call /?
-
echo /?
-
endlocal /?
-
for /?
-
if /?
-
set /?
-
setlocal /?
另请参阅:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。