如何使用Windows批处理文件循环浏览文本文件中的每一行?


244

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

Answers:


304

下面的帖子提供了很大的帮助,但没有执行我在问题中所说的,我需要在整个过程中处理整个流程。这是我发现可以工作的地方。

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

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

用于TechNet上的命令

我感谢所有帖子!


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

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

37
较小的补充:要从命令行以交互方式进行此工作%%A,请%A在上述命令中替换为。否则你会得到%%A was unexpected at this time.
vadipp 2012年

16
仅供参考,如果您需要执行多行命令,请在“ DO”之后加上一个开放的括号“(”,然后再加上几行,以一个封闭的括号“)”结束-您只需将代码放入挡在里面(根据您的口味)。
BrainSlugs83

3
谢谢你的模式。我发现,我不能把周围的文件名引号(“) -对于带有空格的文件名刚刚给我的文件名,例如for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A- > A = myfile.txt任何想法如何阻止这?

1
确保您使用的文件是使用ANSI或UTF8编码的。在尝试使用TYPE命令查看文件并且输出不是我期望的结果之前,我一直在想为什么这不起作用。此时,我注意到由于某种原因该文件已编码为“ UCS-2 BE BOM”!
丹·史蒂文斯

1
值得指出的是,循环中的index参数必须为单个字符。因此,例如%% i很好,但%% index将失败。
文森特

59

从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"

8
澄清“使用引号,则必须使用usebackqfor /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

在批处理文件中,您必须使用%%而不是%:(Type 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”“子例程”。

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

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

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

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


27

改进第一个“ 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---

21

@MrKraus的回答很有启发性。此外,让我补充一点,如果要加载与批处理文件位于同一目录中的文件,请在文件名前添加%〜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命令的开销,则应将目录更改为文本文件的目录。请注意,带空格的文件名仍然需要type。

我希望这可以帮助别人!


批处理文件默认情况下会在当前文件夹中查找,因此无需在文件名前添加前缀。
foxidrive

1
@foxidrive:好的,我听到了。虽然要小心。例如,如果目录被更改,它将查找该目录,而不是批处理文件所在的目录。然后,解决方案将**cd /d %~dp0**在for循环之前调用。这将确保您在批处理文件所在的目录中引用了一个文件。感谢您的观察
Marvin Thobejane 2013年

2
THX和+1的type外观图释
哈莱克斯

我无法解决这个type问题,我不得不引用我的文件名,因为它在另一个包含空格的目录中(该死Program Files)。我遇到了一个错误The system cannot find the file `type.
scragar's

1
@scragar,您的报价正确吗?它必须是'不是`。在我的键盘上,它与@处于同一键上
FrinkTheBrave

18

公认的答案是好的,但是有两个限制。
它将删除空行和以;

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

@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 !!而不是空白。怎么修?
Zimba

可以通过在处理之前将文件拆分为最大行长为8190的临时文件来克服行长限制。然后重组为一个文件。
Zimba

14

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

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

1
彼此相邻的两个百分号%%被视为命令(不是批处理文件)中的单个百分号。
保罗

9

这是我为执行文件夹中的所有SQL脚本而编写的bat文件:

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


6

接受的答案使用cmd.exe

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" } 

这对我有用,包含一个250 MB的文件,其中包含超过200万行,for /F ...命令在数千行之后卡住了。

对于之间的差异foreachForEach-Object,看到挥笔的ForEach和foreach-对象

(鸣谢:在PowerShell中逐行读取文件


1

这里的修改示例在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

完整代码在这里


对上面另一个问题的每条评论 -您可以跳过文件的创建/阅读和使用for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(请注意,^用于对管道进行转义的,因此会将其传递给for而不是直接传递给命令处理器)
user66001

0

要从命令行(使用delayedExpansion)打印文本文件中的所有行:

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=]是为了消除由创建占位符/nfind命令来保存空白行。
Zimba

@jeb:括号]]]问题已解决。请参阅更新,以打印文本文件中的所有行。也适用于Win 10 CMD。
Zimba
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.