需要帮助! 我正在做一个批处理文件,它将替换文件夹中一堆文本文件中的一组字符。我已经找到了可以做到这一点的代码。但它只针对一个文件。是否有一种方法,它可以为文件夹中的所有文件做到这一点。总共有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%
如果你想要一个纯批处理的解决方案,那么最简单的做法是将代码封装在一个子程序中,该子程序将文件名作为参数,然后在一个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
如果你在批处理脚本中使用该命令。
因为你需要做的是替换现有文件中的文本,所以使用类似于 FART 是专门为此设计的。
FART -r "C:\Data\Directory\*.txt" "OldText" "NewText"
该 -r
开关说要处理所有 txt
文件在提供的目录和子文件夹中。
需要注意的是,您可以将 -i
开关,在搜索时忽略案例。