Пакет - объединение двух фрагментов текста в одну строку в цикле - PullRequest
0 голосов
/ 17 марта 2012

Я пытаюсь обработать пакетный файл, чтобы объединить два фрагмента текста в одну строку.Первое имя файла;вторая - первая строка текста, начинающаяся с «Кому:».Я боролся в течение нескольких часов, и это так далеко, как я получил:

@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
)

, и это не работает.Я получаю ошибки или неправильные результаты почти независимо от того, что я записал в строку имени файла;даже не начал испытывать толинную часть.Есть предложения?

Ответы [ 3 ]

2 голосов
/ 17 марта 2012

Вы уже использовали FOR / F для захвата вывода команды DIR.Захват вывода FINDSTR ничем не отличается.

Однако более эффективно использовать простое FOR вместо FOR / F с командой DIR.

Вы использовали %~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

Редактировать Если вас беспокоит, что файл может содержать несколько строк, начинающихся с «Кому:», и вы хотите использовать только первую строку, тогда он возвращается к использованию пакетного файла:

@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, если путь не содержит буквы диска.Проблемы с диском и ! могут быть решены с помощью дополнительных модификаций.

2 голосов
/ 17 марта 2012
@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: «ему назначена соответствующая найденная строка, которая позже будет показана с использованием отложенного расширения.Тем не менее, этот процесс может быть реализован более простым способом, который не требует отложенного расширения, как предложил 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
   )
)
0 голосов
/ 17 марта 2012

Вы не можете назначать и использовать переменные окружения внутри цикла 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
...