替换windows文件夹中一堆文本文件中的一个字符串。

问题描述 投票:1回答:2

需要帮助! 我正在做一个批处理文件,它将替换文件夹中一堆文本文件中的一组字符。我已经找到了可以做到这一点的代码。但它只针对一个文件。是否有一种方法,它可以为文件夹中的所有文件做到这一点。总共有1000个文件的文件夹内。我使用的是Windows 7操作系统。附上我找到的代码,它为一个文件。

谢谢Harry


 @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%
batch-file
2个回答
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( 被使用。

效率低下的其他问题

  • 每输出一行都要进行重定向,速度很慢。最好(更快)在循环外重定向一次。

  • DELRENAME对可以用一条MOVE命令代替

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

  • 我更喜欢让我的临时文件名是原始名称的派生。我通常会在文件名后面加上一个 .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是纯脚本(混合型JScriptbatch),可在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 如果你在批处理脚本中使用该命令。


0
投票

因为你需要做的是替换现有文件中的文本,所以使用类似于 FART 是专门为此设计的。

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

-r 开关说要处理所有 txt 文件在提供的目录和子文件夹中。

需要注意的是,您可以将 -i 开关,在搜索时忽略案例。

© www.soinside.com 2019 - 2024. All rights reserved.