2015-11-01 3 views
1

Нужна помощь! Работа над пакетным файлом, который заменит набор символов из группы текстовых файлов в папке. Я нашел код, который сделает это. Но он работает только для одного файла. Есть ли способ, когда он может сделать это для всех файлов в папке. В общей папке содержится 1000 файлов. Я использую ОС Windows 7. Прикрепление кода, который я нашел, где он используется для одного файла.Замена строки в кучке текстовых файлов в папке Windows

Благодаря Гарри


@echo off 
setlocal enabledelayedexpansion 
set INTEXTFILE=Replace_string.txt 

set OUTTEXTFILE=test_out.txt 
set SEARCHTEXT=Apple 
set REPLACETEXT=Mango 
set SEARCHTEXT=Cat 
set REPLACETEXT=Dog 
set OUTPUTLINE= 

for /f "tokens=1,* delims=¶" %%A in ('"findstr /n ^^ %INTEXTFILE%"') do (
    SET string=%%A 
    for /f "delims=: tokens=1,*" %%a in ("!string!") do set "string=%%b" 
    if "!string!" == "" (
     echo.>>%OUTTEXTFILE% 
    ) else (
     SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%! 
     echo !modified! >> %OUTTEXTFILE% 
) 
) 
del %INTEXTFILE% 
rename %OUTTEXTFILE% %INTEXTFILE% 
+0

использовать 'FOR' во вложенном то есть' for/f 'delims = "%% # in (' dir/b/s" * mask.txt "') do (for/f" tokens = 1, * delims = ¶ "%% A in ('" findstr/n ^^ %% ~ # "') do (....) ...)' – Paul

+0

Обратите внимание, что ваш внутренний цикл 'for/F' удаляет потенциальные ведущие двоеточия': 'из каждой строки; чтобы избежать этого, используйте '' delims = "', затем 'set 'string = %% a" ', а затем' set' string =! string: *: =! "'; это удаляет номер строки и ** first ** ':', добавленный 'forstring', но ничего больше ... вместо' echo! modified! 'вы должны написать' echo.! modified! ', чтобы избежать' ECHO ' Off', когда полная строка соответствует '! SEARCHTEXT!' И 'REPLACETEXT' пуста ... – aschipfl

+1

@aschipfl: Я предлагаю вам не использовать' echo.! Modified! 'Для этой цели. Вы можете использовать 'echo /! Modified!' Или 'echo (! Modified!'. Дополнительная информация в [этот пост] (http://www.dostips.com/forum/viewtopic.php?f=3&t=774). – Aacini

ответ

1

Если вы хотите получить чистое пакетное решение, то самым простым способом является инкапсуляция кода в подпрограмму, которая принимает имя файла в качестве аргумента и вызывает эту процедуру из цикла FOR, который выполняет итерацию файла имена. Это общий подход, который можно использовать для любого кода, который вы хотите запустить итеративно против файлов в папке.

Конечный результат вашего кода не создает и не переименовывает никакие папки, поэтому простой FOR безопасен в использовании. Но если ваш код создает или переименовывает папки, цикл FOR также может обрабатывать вновь созданные или переименованные файлы. Это можно решить, используя FOR/F с помощью команды DIR/B.

Примечание - Я удалил из кода мертвые (неиспользуемые) переменные.

@echo off 
setlocal enabledelayedexpansion 

pushd "c:\path\to\your\folder\containing\files\to\modify" 
for %%F in (*.txt) do call :replace "%%F" 
exit /b 

:replace 
set INTEXTFILE=%1 
set OUTTEXTFILE=test_out.txt 
set SEARCHTEXT=Cat 
set REPLACETEXT=Dog 
for /f "tokens=1,* delims=¶" %%A in ('"findstr /n ^^ %INTEXTFILE%"') do (
    SET string=%%A 
    for /f "delims=: tokens=1,*" %%a in ("!string!") do set "string=%%b" 
    if "!string!" == "" (
     echo.>>%OUTTEXTFILE% 
    ) else (
     SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%! 
     echo !modified! >> %OUTTEXTFILE% 
) 
) 
del %INTEXTFILE% 
rename %OUTTEXTFILE% %INTEXTFILE% 
exit /b 

Но есть много ограничений и неэффективности с кодом, с большим количеством возможностей для улучшения.

Ограничения:

  • Входные и выходные линии должны быть немного длиной менее 8191 байт.

  • Поиск игнорирует случай

  • Строка поиска не может содержать !

  • Строка поиска не может начинаться с =

  • линий, содержащих ! будут повреждены, поскольку задержка расширения активируется, когда %%A расширяется. Это можно решить путем стратегического включения и выключения задержки внутри цикла (ов).

  • Ведущий : будет удален из всех строк, поскольку последовательные символы разделителя рассматриваются как один разделитель.

  • Замена повреждена, если поисковый запрос содержит %%a или %%b или %%A. Этого можно избежать, передав условия поиска и замены в переменные FOR.

  • Определенные символы в пределах условий поиска и/или замены могут вызывать проблемы или требовать сложных escape-последовательностей. Это можно упростить, получив желаемые строки в переменных среды (которые могут по-прежнему нуждаться в escape-последовательностях), а затем использовать задержанное расширение и FOR/F для передачи значений в переменные FOR.

  • Есть неясные ситуации, когда ECHO. может не работать. Единственный безопасный вариант, который гарантированно работает, - ECHO(.

  • Незначительная строка может стать пустой после замены, если строка замены пуста, а пустая строка не будет выводиться должным образом, потому что не было использовано ни ECHO., ни ECHO(.

неэффективностью/другие вопросы

  • Перенаправление выполняется для каждой строки вывода, который является медленным. Лучше (быстрее) перенаправлять один раз за пределы цикла.

  • ДЭС/ПЕРЕИМЕНОВАТЬ пару можно заменить одной командой MOVE

  • ВЫЗОВ является относительно медленным. Лучше всего минимизировать использование CALL, если вы хотите получить самое быстрое решение. Но иногда этого нельзя избежать.

  • Я предпочитаю, чтобы мое имя файла temp было производным от исходного имени. Я обычно присоединять .new расширение к оригинальному названию, так «original.txt» становится «original.txt.new»

Ниже высоко оптимизированный код, который обращается ко всем, кроме первых 4 пункта выше. Это примерно так же эффективно и эффективно, как и чистая партия, если вы хотите использовать FOR/F для чтения файла.

@echo off 
setlocal disableDelayedExpansion 

pushd "c:\path\to\your\folder\containing\files\to\modify" 
set "find=Cat" 
set "repl=Dog" 

setlocal enableDelayedExpansion 
for /f delims^=^ eol^= %%S in ("!find!") do (
    for /f delims^=^ eol^= %%R in ("!repl!") do (
    endlocal 
    for %%F in (*.txt) do (
     for /f "delims=" %%L in ('findstr /n "^" "%%F"') do (
     set "ln=%%L" 
     setlocal enableDelayedExpansion 
     set "ln=!ln:*:=!" 
     if defined ln set "ln=!ln:%%S=%%R!" 
     echo(!ln! 
     endlocal 
    ) 
    ) >"%%F.new" & move /y "%%F.new" "%%F" >nul 
) 
) 
popd 

Для этого требуется большой опыт и знания тайны. Даже после всей работы он все еще имеет следующие ограничения.

  • Вводные и выходные линии должны быть немного меньше 8191 байта.

  • Поиск игнорирует случай

  • Строка поиска не может содержать !

  • Строка поиска не может начинаться с =

Снятие этих ограничений требует нелепое количество медленно и еще более непроницаемый код. Вряд ли это стоит.

Вот почему я отказался от использования чистой партии для обработки текста, и я разработал JREPL.BAT, чтобы обеспечить мощные возможности текстовой обработки регулярных выражений в среде команд Windows. JREPL - это чистый скрипт (гибридный JScript/пакет), который запускается изначально на любом компьютере Windows с XP.

JREPL делает решение настолько простым, что его можно легко запустить непосредственно в командной строке без какого-либо командного файла.

pushd "c:\your\path\with\files\to\be\modified" 
for %F in (*.txt) do call jrepl "Cat" "Dog" /l /f "%F" /o - 
popd 

Поиск с учетом регистра. Вы можете добавить опцию /i, если вы хотите, чтобы поиск игнорировал случай. Измените %F на %%F, если вы используете команду в пакетном скрипте.

+0

Спасибо, он отлично работает для всех файлов. Он заменяет одну« старую строку »на« новую строку ». Но есть ли способ, код может быть настроен так, чтобы замените несколько строк .... в этом случае Apple => Манго Cat => Собака –

0

Поскольку все, что вам нужно сделать, это заменить текст в существующий файл, используйте инструмент как FART, который специально разработан, чтобы сделать это:

FART -r "C:\Data\Directory\*.txt" "OldText" "NewText" 

Коммутатор -r говорит, что обрабатывает все файлы txt в каталоге и подпапках.

Обратите внимание, что вы можете добавить переключатель -i, чтобы игнорировать случай при поиске.

Смежные вопросы