【问题标题】:How to read and print contents of text file line by line?如何逐行读取和打印文本文件的内容?
【发布时间】:2018-07-29 01:54:55
【问题描述】:

因此,我不知道如何从 *.txt 文本文件中一次一个地获取 CMD 回显行,并稍加延迟以使其看起来像是在处理中。

这甚至可以单独使用批次吗?

我尝试过进行研究,但找不到足够的文本操作来执行此操作,但我确实知道如何在每个命令之间暂停以及如何执行循环。

【问题讨论】:

    标签: batch-file cmd


    【解决方案1】:

    让我们假设文本文件TestFile.txt 应该逐行输出,这是一个 ANSI 编码的文本文件,仅包含包含此文本的 ASCII 字符:

    Line 1 is with nothing special. Next line 2 is an empty line.
    
    ;Line 3 with a semicolon at beginning.
       Line 4 has leading spaces.
        Line 5 has a leading horizontal tab.
    Line 6 is with nothing special. Next line 7 has just a tab and four spaces if used internet browser does not remove them.
            
    Line 8 is ! with exclamation marks ! in line!
    ? Line 9 starts with a question mark.
    : Line 10 starts with a colon.
    ] Line 11 starts with a closing square bracket.
    

    下面的批处理文件逐行输出此文本文件,每行之间延迟一秒,但第二行完全为空。

    @echo off
    title Read line by line with delay
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem Use command TIMEOUT by default for 1 second delay. But use
    rem PING in case of TIMEOUT does not exist as on Windows XP.
    set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
    if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
    
    for /F "usebackq eol=¿ delims=" %%I in ("TestFile.txt") do (
        echo(%%I
        %DelayCommand% >nul
    )
    endlocal
    pause
    

    eol= 后面的奇怪字符¿ 是一个反问号,十六进制 Unicode 值 00BF 用于正确输出第三行。由于重新定义了行尾字符,因此不会输出开头带有反问号的行。

    此批处理文件代码并非旨在输出具有任何类型的 character encoding 的任何类型的文本文件,而与包含文本文件的字符无关。 Windows 命令行环境不是为输出任何文本文件而设计的。

    也可以使用不带引号的不同语法来指定 FOR 选项 delimseolusebackq 来定义一个空的分隔符列表 没有行尾字符:

    @echo off
    title Read line by line with delay
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem Use command TIMEOUT by default for 1 second delay. But use
    rem PING in case of TIMEOUT does not exist as on Windows XP.
    set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
    if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
    
    for /F usebackq^ delims^=^ eol^= %%I in ("TestFile.txt") do (
        echo(%%I
        %DelayCommand% >nul
    )
    endlocal
    pause
    

    感谢 aschipfl 提供三个 FOR 选项的替代语法,使用转义字符 ^ 转义非双引号选项字符串中的等号和空格以由 @ 解释987654334@ 字符串usebackq delims= eol= 作为for /F一个 参数字符串。

    (,而不是通常用于输出正确的第7行的空格,只有一个制表符和一些普通空格。另请参阅 DosTips 论坛主题 ECHO. FAILS to give text or blank line - Instead use ECHO/echo/%%I 不纠正以问号开头的第 9 行输出。

    无法使用 FOR 不忽略空行的选项进行定义。但是可以使用 FINDFINDSTR 输出一个文本文件,其中所有行都以行号开头,因此不再有空行。行号括在方括号 (FIND) 中或用冒号 (FINDSTR) 与行的其余部分分隔。可以仅将]: 的第一个sequence 之后的字符串分配给循环变量,这在大多数情况下表示文本文件中的整行。但如果文本文件中的一行偶然以]: 开头,FOR 也会删除此分隔符。解决方案是这段代码:

    @echo off
    title Read line by line with delay
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem Use command TIMEOUT by default for 1 second delay. But use
    rem PING in case of TIMEOUT does not exist as on Windows XP.
    set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
    if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
    
    for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "TestFile.txt" 2^>nul') do (
        set "Line=%%I"
        setlocal EnableDelayedExpansion
        echo(!Line:*:=!
        endlocal
        %DelayCommand% >nul
    )
    endlocal
    pause
    

    FINDSTR 在单独的命令进程中执行的带有行号和冒号的整行输出由 FOR 使用%ComSpec% /c' 中的命令行作为额外的参数被分配给循环变量I,它被分配在环境变量Line旁边。

    然后根据需要为下一行启用延迟扩展,从而在创建当前环境变量的副本之前将当前环境变量列表的地址以及当前目录路径、命令扩展的状态和延迟扩展的状态推送到堆栈上列表。

    接下来将输出环境变量Line 的值,但是将直到第一个冒号的所有内容都替换为任何内容,这会导致实际行的输出存储在没有行号的文本文件中以及由 FINDSTR 在开头插入的冒号。

    最后将创建的环境变量列表副本从内存中删除,并将之前的延迟扩展和命令扩展状态从堆栈中弹出并设置,并将当前目录路径再次设置为当前目录和环境变量的先前地址list 被恢复以恢复环境变量列表。

    为文本文件中的每一行运行命令setlocal EnableDelayedExpansionendlocal 当然效率不高正确分配给环境变量Line,然后处理下一个更正Line 的值。由于每条线路的输出之间存在一秒钟的延迟,因此效率损失在这里并不是真正的问题。

    要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

    • echo /?
    • endlocal /?
    • findstr /?
    • for /?
    • if /?
    • ping /?
    • rem /?
    • set /?
    • setlocal /?

    【讨论】:

    • 您应该使用echo( 而不是echo/(想象一行包含?)。而且我不会在批处理文件中使用(不可见的)控制字符,例如换页符;你可以在这里使用不带引号的语法for /F usebackq^ delims^=^ eol^= %%A。无论如何,你到底为什么要回答这个离题的问题?
    【解决方案2】:

    尽管您的问题离题了,但我决定将其包含在内,因为已经有两个答案,并且可以使用一行来实现。

    来自批处理文件:

    @For /F Tokens^=1*Delims^=]^ EOL^= %%A In ('Find /N /V ""^<"C:\test.txt"') Do @Echo(%%B&>Nul PathPing 127.0.0.1 -n -q 1 -p 450
    

    从命令提示符:

    For /F Tokens^=1*Delims^=]^ EOL^= %A In ('Find /N /V ""^<"C:\test.txt"') Do @Echo(%B&>Nul PathPing 127.0.0.1 -n -q 1 -p 1350
    

    这两个示例都没有省略源文件中的空行 C:\test.txt可以根据需要进行更改
    我使用 PathPing 来表示“微小延迟”,因为似乎更可控; 要调整延迟,您只需更改最后一个数字,直到找到最满意的输出

    【讨论】:

    • 空行不跳过是对的,因为使用FIND输出所有行号在方括号内的行,让FOR忽略直到 ] 的第一个 序列 结尾的所有内容。但我想补充一点,在开头有一个或多个] 的行上,此解决方案也不会输出这些右方括号,例如使用findstr /N "^" "C:\Test.txt" 和使用: 作为FOR 中的分隔符忽略后跟冒号的行号,导致在行首不输出冒号。
    • @Mofi,同意,但是以] 开头的行的可能性远小于空行或以: 开头的行! 事实上,因为字符通常应该关闭前面的[,所以它应该只出现在从固定行长例程输出的行的开头或从使用它的图像输出的行的开头。
    • 我同意,有很多文本文件以: 开头,例如批处理文件或汇编文件。在行首带有右方括号的文本文件非常罕见。在过去 25 年中,我见过的唯一一个以 ] 开头的文本文件是包含 CDATA 部分的 XML 文件,其中嵌入的数据以行结尾结尾。因此,您使用 FIND 的决定绝对是一个非常好的决定,因为它适用于大约 99.99999999% 的所有文本文件,这就是我赞成您的单一命令行解决方案的原因。
    • 作为对上述@Mofi 的补充,在我对 XML 的了解可能有限中,我发现 CDATA 部分倾向于缩进闭合,即它们的行开始空格后跟右方括号。在这些情况下,我的代码应该按预期工作。
    • 有两种类型的 XML 文件,一种是为人们查看/编辑而设计的,格式良好,带有换行符和缩进,另一些由程序为程序创建的文件通常没有换行符并且没有缩进来减小大小并加快读/写速度。 ]]&gt; 用于关闭 CDATA 部分应位于嵌入数据部分真正结束的 XML 文件中,因为此处结束该部分。通过将]]&gt; 额外放在新行缩进正确意味着将行尾和空格/制表符附加到数据实际上没有的数据部分。根据数据,这可能不是很好。
    【解决方案3】:

    试试这个批处理脚本:

    @echo off
    Title Read line by line with delay
    set "InputFile=TestFile.txt"
    set "delay=1" Rem Delay one seconds, you can change it for your needs
    setlocal enabledelayedexpansion
    for /f "tokens=*" %%A in ('Type "%InputFile%"') do (
      set /a N+=1
      set "Line[!N!]=%%A"
    )
    
    for /l %%i in (1,1,%N%) do (
        echo !Line[%%i]!
        Timeout /T %delay% /nobreak>nul
    )
    pause
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多