如何替换Windows批处理文件中的子字符串


75

谁能告诉我在Windows中使用批处理文件...如何从文件中读取并将bath包含=的文件中的string =替换bath Abath Bbath XYZbathABC为字符串,hello以便输出类似于hello Ahello Bhello XYZhelloABC

Answers:


104

Andriy M扩展,是的,您可以从一个文件执行此操作,即使是多行的文件也可以

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "INTEXTFILE=test.txt"
set "OUTTEXTFILE=test_out.txt"
set "SEARCHTEXT=bath"
set "REPLACETEXT=hello"

for /f "delims=" %%A in ('type "%INTEXTFILE%"') do (
    set "string=%%A"
    set "modified=!string:%SEARCHTEXT%=%REPLACETEXT%!"
    echo !modified!>>"%OUTTEXTFILE%"
)

del "%INTEXTFILE%"
rename "%OUTTEXTFILE%" "%INTEXTFILE%"
endlocal

编辑

感谢David Nelson,我更新了脚本,因此它不再具有硬编码值。


1
它很好并且可以使用,但是由于某些原因,它确实会删除空白行。Gonzalezea在以下链接上的回答解决了空行剥离问题:stackoverflow.com/a/20227248/280109
user280109 2014年

1
供读者考虑使用代码的一些信息:FOR忽略空行,并且由于这;是option的默认值,因此该代码也以行开头eol!由于此代码要求启用延迟扩展,因此无法正确处理包含一个或多个行的行。由于替换字符串为空字符串且搜索字符串与整行匹配,因此删除了环境变量时的ECHO输出。搜索字符串不能包含等号,因为在替换表达式中具有特殊含义。echo is off.modified=
Mofi '18

如果我需要像使用另一个一样更改两个单独的字符串,此代码是否会大不相同set "modified1=...
zygimantus

哇,这对于这么简单的事情来说似乎太过分了。
索伦

45
SET string=bath Abath Bbath XYZbathABC
SET modified=%string:bath=hello%
ECHO %string%
ECHO %modified%

编辑

起初并没有看到您希望在替换之前先从文件中读取字符串。

好吧,使用批处理文件,您没有太多处理文件的便利。在这种情况下,您必须阅读一行,进行替换,然后输出修改后的行,然后...然后呢?如果您需要替换所有文件中所有'bath'事件,则必须使用循环:

@ECHO OFF
SETLOCAL DISABLEDELAYEDEXPANSION
FOR /F %%L IN (file.txt) DO (
  SET "line=%%L"
  SETLOCAL ENABLEDELAYEDEXPANSION
  ECHO !line:bath=hello!
  ENDLOCAL
)
ENDLOCAL

您可以将重定向添加到文件:

  ECHO !line:bath=hello!>>file2.txt

或者,您可以将重定向应用于批处理文件。它必须是另一个文件。

编辑2

添加了延迟扩展的适当切换,以正确处理某些具有批处理脚本语法特殊意义的字符,例如!^等。(谢谢,吉布!)


是的,因此至少对于字符串而言,可以使用Windows批处理功能(与DOS批处理或更旧的Windows版本不兼容)。但是,如果这对文件(特别是多行文件)有效,我会感到惊讶。
schnaader 2011年

1
@schnaader:有可能尝试看看Batch FindAndReplace
jeb 2011年

@jeb:好的,至少有可能,感谢您的链接。无论如何,我的答案中的“非常复杂”和“不兼容”都适用于此。
schnaader 2011年

1
@schnaader:通常,它不像其他一些脚本工具可能那样优雅。我怀疑,最初他们被称为批处理文件,只是意味着批处理执行(命令)。但是我在那里可能是错的。不管怎样,与cscriptPowerShell在那里,我有时觉得他们会完全废止批处理文件,如果它在所有使用过Windows的境界不是因为剧本的大概数量庞大依然。
Andriy M

@Andriy L:它可改善是安全与!^在与切换接通和断开延迟扩展的内容,像改进BatchSubstitute
杰布

13

为了避免空行跳过(使conf文件具有可读性),我将aflat和jeb答案(在此处)组合为以下内容:

@echo off
setlocal enabledelayedexpansion
set INTEXTFILE=test.txt
set OUTTEXTFILE=test_out.txt
set SEARCHTEXT=bath
set REPLACETEXT=hello
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%

您可能还需要设置正确的代码页,以避免文本文件中的非ansi字符出现问题:例如,chcp 65001对于UTF8:请参阅Windows批处理中的Echo UTF-8字符
TmTron

4

为了避免批处理解析器出现问题(例如,感叹号),请查看搜索问题并替换批处理文件

修改aflat的脚本之后,将包含感叹号之类的特殊字符。

@echo off
setlocal DisableDelayedExpansion
set INTEXTFILE=test.txt
set OUTTEXTFILE=test_out.txt
set SEARCHTEXT=bath
set REPLACETEXT=hello
set OUTPUTLINE=

for /f "tokens=1,* delims=¶" %%A in ( '"type %INTEXTFILE%"') do (
    SET string=%%A
    setlocal EnableDelayedExpansion
    SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%!

    >> %OUTTEXTFILE% echo(!modified!
    endlocal
)
del %INTEXTFILE%
rename %OUTTEXTFILE% %INTEXTFILE%


-1

为了避免跳过空白行,只需替换以下内容:

echo !modified! >> %OUTTEXTFILE%

有了这个:

echo.!modified! >> %OUTTEXTFILE%

2
这不是问题的答案
jeb

-8

如果您有Ruby for Windows

C:\>more file
bath Abath Bbath XYZbathABC

C:\>ruby -pne "$_.gsub!(/bath/,\"hello\")" file
hello Ahello Bhello XYZhelloABC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.