Batch file 替换windows文件夹中一组文本文件中的字符串

Batch file 替换windows文件夹中一组文本文件中的字符串,batch-file,Batch File,需要帮助!处理一个批处理文件,该批处理文件将替换文件夹中一组文本文件中的一组字符。我已经找到了可以这样做的代码。但它只适用于一个文件。是否有一种方法可以对文件夹中的所有文件执行此操作。文件夹中总共有1000个文件。我使用的是Windows7操作系统。将我找到的代码附加到一个文件的位置 谢谢 哈利 由于您只需替换现有文件中的文本,因此请使用专门为此设计的工具: FART -r "C:\Data\Directory\*.txt" "OldText" "NewText" -r开关指示处理所提供目录

需要帮助!处理一个批处理文件,该批处理文件将替换文件夹中一组文本文件中的一组字符。我已经找到了可以这样做的代码。但它只适用于一个文件。是否有一种方法可以对文件夹中的所有文件执行此操作。文件夹中总共有1000个文件。我使用的是Windows7操作系统。将我找到的代码附加到一个文件的位置

谢谢 哈利



由于您只需替换现有文件中的文本,因此请使用专门为此设计的工具:

FART -r "C:\Data\Directory\*.txt" "OldText" "NewText"
-r
开关指示处理所提供目录和子文件夹中的所有
txt
文件


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

如果您想要纯批处理解决方案,那么最简单的方法是将代码封装在以文件名为参数的子例程中,并从迭代文件名的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命令替换

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

  • 我更喜欢将我的临时文件名作为原始名称的派生名称。我通常在原始名称后附加一个
    .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字节

  • 搜索忽略了案例

  • 搜索字符串不能包含
    =
    或以
    ~
    *
    开头

  • 替换字符串不能包含

消除这些限制需要大量缓慢甚至难以理解的代码,这几乎不值得

这就是我放弃使用纯批处理进行文本处理的原因,我开发它是为了向Windows命令环境提供强大的正则表达式文本处理功能。JREPL是纯脚本(混合JScript/batch),从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

在嵌套中使用
FOR
,即
FOR/F“delims=“%%#in('dir/b/s”*mask.txt')do(FOR/F“tokens=1,*delims=”“%a in('“findstr/n^^%~#“')do(…)
注意,您的内部
for/F
循环会从每一行中删除潜在的前导冒号
;要避免这种情况,请使用
“delims=”
,然后
设置“string=%a”
,然后
设置“string=!string::=!”!“
;这将删除行号和第一个
前面的
字符串
,但没有其他内容…而不是
echo!已修改!
您应该写入
echo。!已修改!
以避免
echo关闭pushd "c:\your\path\with\files\to\be\modified"
for %F in (*.txt) do call jrepl "Cat" "Dog" /l /f "%F" /o -
popd