替换Windows文件夹中的一堆文本文件中的字符串

时间:2015-11-01 00:40:18

标签: batch-file

需要帮助!处理批处理文件,该文件将替换文件夹中的一堆文本文件中的一组字符。我找到了会这样做的代码。但它只适用于一个文件。有没有办法可以为文件夹中的所有文件执行此操作。文件夹中总共有1000个文件。我使用的是Windows 7操作系统。附上我在一个文件中找到的代码。

由于 哈利

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

2 个答案:

答案 0 :(得分: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变量可以避免这种情况。

  • 搜索和/或替换术语中的某些字符可能会导致问题或需要复杂的转义序列。这可以通过在环境变量中获取所需的字符串(可能仍需要转义序列),然后使用延迟扩展和FOR / F将值传输到FOR变量来简化。

  • ECHO.失败的模糊情况。保证可以使用的唯一安全变体是ECHO(

  • 如果替换字符串为空,则非空行可能在替换后变为空,并且由于未使用ECHO.ECHO(,空行将无法正确输出。

效率低下/其他问题

  • 对每行输出执行重定向,这很慢。更好(更快)在循环外重定向。

  • DEL / RENAME对可以用单个MOVE命令替换

  • CALL相对较慢。如果您想要最快的解决方案,最好尽量减少使用CALL。但有时无法避免。

  • 我更喜欢将我的临时文件名作为原始名称的衍生物。我通常在原始名称附加.new扩展名,因此“original.txt”变为“original.txt.new”

以下是经过高度优化的代码,可解决上述所有问题。如果你想使用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 /批处理),可以在XP之后的任何Windows机器上本机运行。

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

答案 1 :(得分:0)

由于您需要做的只是替换现有文件中的文字,因此请使用FART之类的专门用于执行此操作的工具:

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

-r开关表示处理提供的目录和子文件夹中的所有txt个文件。

请注意,您可以添加-i开关,以便在搜索时忽略大小写。