如何使用 Windows 批处理文件遍历文本文件中的每一行?

Posted

技术标签:

【中文标题】如何使用 Windows 批处理文件遍历文本文件中的每一行?【英文标题】:How do you loop through each line in a text file using a windows batch file? 【发布时间】:2010-09-14 10:21:01 【问题描述】:

我想知道如何使用 Windows 批处理文件循环遍历文本文件中的每一行并连续处理每一行文本。

【问题讨论】:

【参考方案1】:

我需要将整条生产线作为一个整体进行处理。这是我发现的工作。

for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

带有星号 (*) 的 tokens 关键字将提取整行的所有文本。如果您不输入星号,它只会拉出该行的第一个单词。我认为它与空格有关。

For Command on TechNet


如果您的文件路径中有空格,则需要使用usebackq。例如。

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A

【讨论】:

一个小补充:要从命令行交互地进行这项工作,请将上述命令中的%%A 替换为%A。否则你会得到%%A was unexpected at this time. 仅供参考,如果您需要执行多行命令,请在“DO”之后放置一个左括号“(”,然后在几行之后,用右括号“)”结束它 - - 你可以把你的代码块放在里面(缩进你的口味)。 感谢您提供的模式。我发现我不能在文件名周围加上引号(“)——对于带空格的文件名,只给我文件名。例如for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A --> A = myfile.txt。任何想法如何阻止这个? 确保您使用的文件是用 ANSI 或 UTF8 编码的。我一直在摸索为什么这不起作用,直到我尝试使用 TYPE 命令查看文件并且输出不是我所期望的。此时我注意到该文件由于某种原因被编码为“UCS-2 BE BOM”! 值得指出的是,循环中的索引参数必须是单个字符。因此,例如 %%i 很好,但 %%index 会失败。【参考方案2】:

来自 Windows 命令行参考:

要解析文件,忽略注释行,输入:

for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do @echo %i %j %k

此命令解析 Myfile.txt 中的每一行,忽略以分号开头的行并将每行的第二个和第三个标记传递给 FOR 正文(标记由逗号或空格分隔)。 FOR 语句的主体引用 %i 来获取第二个令牌, %j 来获取第三个令牌,以及 %k 来获取所有剩余的令牌。

如果您提供的文件名包含空格,请在文本周围使用引号(例如,“文件名”)。要使用引号,您必须使用 usebackq。否则,引号将被解释为定义要解析的文字字符串。

顺便说一句,您可以在以下位置找到大多数 Windows 系统上的命令行帮助文件:

 "C:\WINDOWS\Help\ntcmds.chm"

【讨论】:

toclarify"要使用引号,必须使用usebackq"for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt") 为什么省略了第一个标记?【参考方案3】:

在批处理文件中,您必须使用%% 而不是%:(输入help for

for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF

这是做什么的: for 命令末尾的 "do call :process %%i %%j %%k" 将 for 命令中获取的信息从 myfile.txt 传递到 "process" 'subroutine'。

当您在批处理程序中使用 for 命令时,您需要对变量使用双 % 符号。

以下行将这些变量从 for 命令传递到进程“子例程”,并允许您处理此信息。

set VAR1=%1
 set VAR2=%2
 set VAR3=%3

如果需要更多示例,我愿意分享这个精确设置的一些非常高级的用法。当然,根据需要添加 EOL 或 Delims。

【讨论】:

【参考方案4】:

改进第一个“FOR /F..”答案: 我要做的是调用执行 MyList.txt 中列出的每个脚本,所以它对我有用:

for /F "tokens=*" %A in  (MyList.txt) do CALL %A ARG1

--或者,如果你想在多行上做:

for /F "tokens=*" %A in  (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)

编辑:上面给出的例子是从命令提示符执行 FOR 循环;从批处理脚本中,需要添加额外的 %,如下所示:

---START of MyScript.bat---
@echo off
for /F "tokens=*" %%A in  ( MyList.TXT) do  (
   ECHO Processing %%A.... 
   CALL %%A ARG1 
)
@echo on
;---END of MyScript.bat---

【讨论】:

【参考方案5】:

@MrKraus 的answer 很有启发性。此外,让我补充一点,如果要加载与批处理文件位于同一目录中的文件,请在文件名前加上 %~dp0。这是一个例子:

cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

注意::如果您的文件名或目录(例如上例中的 myfile.txt)有空格(例如 'my file.txt' 或 'c:\Program Files'),使用:

for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A

,使用 type 关键字调用 type 程序,该程序显示文本文件的内容。如果您不想承受调用 type 命令的开销,您应该将目录更改为文本文件的目录。请注意,带有空格的文件名仍然需要类型。

我希望这对某人有帮助!

【讨论】:

不需要在文件名前加上前缀,因为批处理文件默认会在当前文件夹中查找。 @foxidrive:好的,我听到了。虽然应该小心。例如,如果更改了一个目录,它将查看该目录而不是批处理文件所在的目录。然后解决方案将在 for 循环之前调用 **cd /d %~dp0**。这将确保您引用批处理文件所在目录中的文件。感谢您的观察 感谢 type walkaround 的 +1 我无法让type 工作,我不得不引用我的文件名,因为它位于包含空格的不同目录中(该死的你Program Files)。我收到一个错误The system cannot find the file `type. @scragar,你有正确的报价吗?它必须是“而不是”。在我的键盘上,它与 @ 位于同一个键上【参考方案6】:

接受的答案很好,但有两个限制。 它丢弃空行和以;开头的行

要阅读任何内容的行,您需要延迟扩展切换技术。

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
    ENDLOCAL
)

Findstr 用于在每行前面加上行号和冒号,因此空行不再是空的。

在访问%%a参数时需要禁用DelayedExpansion,否则感叹号!和插入符号^将丢失,因为它们在该模式下具有特殊含义。

但是要从行中删除行号,需要启用延迟扩展。set "var=!var:*:=!" 会删除第一个冒号之前的所有冒号(使用delims=: 也会删除行首的所有冒号,不仅来自 findstr)。 endlocal 为下一行再次禁用延迟扩展。

现在唯一的限制是 ~8191 的行长度限制,但似乎没有办法克服这个问题。

【讨论】:

Win 10 不允许在命令行上使用 setlocal。当我在 CMD 上运行代码时,我得到 !var!而不是空格。如何解决? 可以通过在处理前将文件拆分为最大行长 8190 的临时文件来克服行长限制。然后重新组合成一个文件。 Zimba:- 我想你想创建一个批处理文件并粘贴整个代码 sn-p。我相信你已经弄清楚了。然而,它可能会帮助下一个人。 Jeb:- echo 行当前显示为:- echo (!var!我认为它应该是:- echo !var!我不知道为什么我们需要发出额外的 ( Nice One。感谢您放置在公共领域的哑弹像我一样。 @DanielAdeniji echo(!var! 是正确的(没有空格),它避免了像 ONOFF/? 这样的 var 中的内容问题另见:ECHO. FAILS to give text or blank line - Instead use ECHO/ @jeb。谢谢指正。【参考方案7】:

或者,您可以排除引号中的选项:

FOR /F %%i IN (myfile.txt) DO ECHO %%i

【讨论】:

两个相邻的百分号 %% 在命令(不是批处理文件)中被视为单个百分号。【参考方案8】:

这是我编写的一个 bat 文件,用于执行文件夹中的所有 SQL 脚本:

REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************

dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp

【讨论】:

【参考方案9】:

如果您有一个 NT 系列 Windows(带有cmd.exe 作为外壳的 Windows),请尝试使用the FOR /F command。

【讨论】:

【参考方案10】:

使用cmd.exe

接受的anwser
for /F "tokens=*" %F in (file.txt) do whatever "%F" ...

仅适用于“普通”文件。文件很大时它会惨遭失败。

对于大文件,你可能需要使用 Powershell 和类似的东西:

[IO.File]::ReadLines("file.txt") | ForEach-Object  whatever "$_" 

或者如果你有足够的内存:

foreach($line in [System.IO.File]::ReadLines("file.txt"))  whatever "$line"  

这对我来说适用于包含超过 200 万行的 250 MB 文件,其中 for /F ... 命令在几千行后卡住了。

foreachForEach-Object 之间的区别,请参阅Getting to Know ForEach and ForEach-Object。

(学分:Read file line by line in PowerShell)

【讨论】:

【参考方案11】:

在此处修改示例以列出我们在 Heroku 上的 Rails 应用程序 - 谢谢!

cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i

完整代码here.

【讨论】:

Per comment to another question above - 您可以跳过文件创建/读取,只需使用 for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do... (注意添加 ^ 用于转义管道,以便将其传递给for 而不是直接发给命令处理器)【参考方案12】:

从命令行打印文本文件中的所有行(使用延迟扩展):

set input="path/to/file.txt"

for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)

适用于前导空格、空行、空白行。

在 Win 10 CMD 上测试

【讨论】:

上帝试一试,但是您的第一个示例从行中删除了前导 ]]],第二个示例删除了空行和以空格开头的行 第二个是为了删除空行。如果文本文件中的任何行以] 开头,第一个可以修改delims,例如。用一些没有的字符替换,或者像退格或铃这样的控制字符;它们通常不会在文本文件中找到。 delims=]的原因是为了去掉find命令的/n创建的占位符,保留空行。 @jeb: 括号 ]]] 问题已修复。请参阅更新,以打印文本文件中的所有行。也适用于 Win 10 CMD。 但现在它在文本中出现感叹号失败,例如This bang ! disappears。顺便说一句,您不需要delim=[ 因为set a=!a:*]=]! 也会删除它,而echo:!a:~1! 不是必需的,您可以将替换更改为set a=!a:*]=! @jeb:刚刚检查过,即使有感叹号仍然有效。请参阅编辑中的 scnshot。你有延迟扩展吗? delim=[ 的想法是只保留带有空格的行,因为它不是内容的一部分,所以要用 set a=!a:*]=]! 删除。 set a=!a:*]=]! 的原因是 set a=!a:*]=! 在初始测试中不起作用。现在两者都可以在最终代码中使用正确的echo 格式。

以上是关于如何使用 Windows 批处理文件遍历文本文件中的每一行?的主要内容,如果未能解决你的问题,请参考以下文章

C++如何遍历文件夹?

无法遍历文件名中带有空格的文件、Windows 批处理文件和图像魔法

如何使用 Windows 命令行环境查找和替换文件中的文本?

如何使用Windows命令行环境查找和替换文件中的文本?

如何逐行读取批处理文件中多余字符的文本文件?允许限制行长。(Windows,批处理脚本)

从文本文件中读取第一行的 Windows 批处理命令