批处理 - 在一个循环中的一行上组合两段文本

时间:2012-03-16 21:05:05

标签: loops batch-file for-loop concatenation filenames

我正在尝试处理批处理文件,以便在一行中合并两段文本。第一个是文件名;第二行是以“To:”开头的第一行文本。我一直在苦苦挣扎几个小时,这是我已经得到的:

@echo off
IF EXIST fullnames.txt DEL fullnames.txt
FOR /F %%g IN ('dir /b *.eml') DO (
SET filename=%~f1
SET toline=FINDSTR /B /C "To: "
ECHO %FILENAME%%TOLINE% >> fullnames.txt
)

它不起作用。无论我为文件名行放下什么,我都会收到错误或错误的结果;甚至没有开始测试toline部分。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

您已使用FOR / F捕获DIR命令的输出。捕获FINDSTR的输出也不例外。

但是,使用简单的FOR代替使用DIR命令的FOR / F更有效。

我认为您打算使用%~f1%%~fg

您无法使用%var%扩展括号内的变量集,您必须使用!var!延迟扩张而不是。从命令行键入SET /?以获取更多信息 - 阅读以开头的部分“最后,支持延迟环境变量扩展 加入...“

但是,在您的情况下,您可以轻松避免使用延迟扩展(不是这是一个问题)。

不是删除任何现有的“fullnames.txt”然后将输出附加到它,而是将整个构造括在括号中并使用覆写模式将所有输出重定向到文件更有效。

@echo off
(
  for %%F in (*.eml) do (
    for "delims=" %%A in ('findstr /b /c:"To: " "%%F"') do echo %%F %%A
  )
) >fullnames.txt

但上述解决方案虽然简单,但却比它需要的复杂得多。

FINDSTR可以处理使用通配符指定的多个文件,它会在每个匹配行前面加上文件名后跟冒号。

您甚至无需使用批处理文件即可从命令行获取结果(或者您可以将其放在批处理文件中):

findstr /b /c:"To: " *.eml >fullnames.txt

修改
如果您担心文件可能包含以“To:”开头的多行,并且您只想使用第一行,那么它将返回使用批处理文件:

@echo off
setlocal enableDelayedExpansion
set "prevFile="
(
  for /f "tokens=1* delims=:" %%A in ('findstr /b /c:"To: " *.eml') do (
    if "%%A" neq "!prevFile!" echo %%A: %%B
    set "prevFile=%%A"
  )
) >fullnames.txt

如果文件名包含!,则上述解决方案可能会失败。此外,只要路径不包含驱动器号,路径就可以与*.eml一起使用。驱动和!问题都可以通过其他修改来解决。

答案 1 :(得分:2)

@echo off
setlocal EnableDelayedExpansion
if exist fullnames.txt del fullnames.txt
for %%f in (*.eml) do (
   set toline=
   for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
      if not defined toline set "toline=%%l"
   )
   echo %%f!toline! >> fullnames.txt
)

编辑添加了更简单的方法

set toline=命令在处理每个文件之前删除'toline'变量,因此只有第一个“To:”匹配行被分配给它,然后使用Delayed Expansion显示。但是,正如dbenham建议的那样,这个过程可以通过一种不需要延迟扩展的简单方式实现:

@echo off
if exist fullnames.txt del fullnames.txt
for %%f in (*.eml) do (
   set firstFind=
   for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
      if not defined firstFind set firstFind=now & echo %%f%%l >> fullnames.txt
   )
)

答案 2 :(得分:0)

您无法在for循环中分配和使用环境变量。使用延迟变量扩展或调用子程序。

延迟会看起来像这样

    setlocal EnableDelayedExpansion

    @echo off
    IF EXIST fullnames.txt DEL fullnames.txt
    FOR /F %%g IN ('dir /b *.eml') DO (
    SET filename=%~f1
    SET toline=FINDSTR /B /C "To: "
    ECHO !FILENAME!!TOLINE! >> fullnames.txt
    )

然而,无论如何它看起来都不会正常工作。我会这样做

    FOR /F %%g IN ('dir /b *.eml') DO call :process %%g
    goto :eof

    :process
    SET filename=%~f1
    SET toline=FINDSTR /B /C "To: "
    ECHO %FILENAME%%TOLINE% >> fullnames.txt