How to replace substrings in windows batch file
Asked Answered
N

7

87

Can anyone tell me using batch file in windows ...how to read from a file and replace string=bath from file containing=bath Abath Bbath XYZbathABC with string hello so that the output is like hello Ahello Bhello XYZhelloABC

Nostradamus answered 11/3, 2011 at 14:10 Comment(0)
F
112

Expanding from Andriy M, and yes you can do this from a file, even one with multiple lines

@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

EDIT

Thanks David Nelson, I have updated the script so it doesn't have the hard coded values anymore.

Fanaticism answered 11/3, 2011 at 15:31 Comment(4)
its nice and it works, but it does strip out blank lines for some reason. Gonzalezea's answer at the following link fixes the blank line stripping issue: https://mcmap.net/q/237746/-how-to-replace-substrings-in-windows-batch-fileAlembic
Some information for readers thinking about using the code: FOR ignores empty lines and with this code also lines starting with ; because of being the default for option eol. Lines with one or more ! are not processed correct with this code because of enabled delayed expansion required by this code. ECHO outputs echo is off. in case of environment variable modified is deleted because the replace string is an empty string and the search string matches the entire line. The search string can't contain an equal sign because of = has a special meaning in substitution expression.Carmichael
Is this code very different if I need to change two separate string like using another set "modified1=...?Napoleonnapoleonic
Wow, this seems to be overkill for such a simple thing.Broker
T
57
SET string=bath Abath Bbath XYZbathABC
SET modified=%string:bath=hello%
ECHO %string%
ECHO %modified%

EDIT

Didn't see at first that you wanted the replacement to be preceded by reading the string from a file.

Well, with a batch file you don't have much facility of working on files. In this particular case, you'd have to read a line, perform the replacement, then output the modified line, and then... What then? If you need to replace all the ocurrences of 'bath' in all the file, then you'll have to use a loop:

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

You can add a redirection to a file:

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

Or you can apply the redirection to the batch file. It must be a different file.

EDIT 2

Added proper toggling of delayed expansion for correct processing of some characters that have special meaning with batch script syntax, like !, ^ et al. (Thanks, jeb!)

Tyra answered 11/3, 2011 at 14:21 Comment(9)
OK, so at least for a string, it's possible with Windows batch features (not compatible with DOS batch or older Windows versions). But I'd be surprised if this works on a file (especially a file with multiple lines).Viridian
@schnaader: It is possible, try a look at Batch FindAndReplaceOdessaodetta
@jeb: OK, so it's possible at least, thanks for the link. Anyway, both "very complicated" and "incompatible" from my answer apply here.Viridian
@schnaader: Generally, it's not as elegant as some other scripting tools might do. I suspect, that initially they were called batch files simply meaning batch executing (of commands). But I may be wrong there. Anyway, what with cscript and PowerShell being there, I sometimes think they would have scrapped batch files altogether if it were not for the probably enormous number of scripts still in use all over the Windows realm.Tyra
@Andriy M: It can be improved to be safe with ! and ^ in the content with toggling the delayed expansion on and off, like in Improved BatchSubstituteOdessaodetta
@jeb: You mean, using double quotes with the assignment, and toggling the delayed expansion around the ECHO line only? The other measures taken in the batch script by your link seem to only have to do with parametrising the searched and replaced strings.Tyra
@Andriy M: No, the point is to disable it when the for-loop variable %%a is expanded and enable then the delayed expansion, for every single loop, else ! are lostOdessaodetta
@jeb: Seems clear now. But it would be great if you take a look at the correction, just to make sure if I got that right. Thank you very much anyway!Tyra
@Andriy M: It's perfect safe now, only a typo is left at %%L instead of %%a (and I can't edit it)Odessaodetta
L
12

To avoid blank line skipping (give readability in conf file) I combine aflat and jeb answer (here) to something like this:

@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%
Leucocratic answered 26/11, 2013 at 20:25 Comment(1)
you may also want to set the correct code-page, to avoid problems with non-ansi characters in the text-file: e.g. chcp 65001 for UTF8: see Echo UTF-8 characters in windows batchImide
T
4

To avoid problems with the batch parser (e.g. exclamation point), look at Problem with search and replace batch file.

Following modification of aflat's script will include special characters like exclamation points.

@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%
Toting answered 4/6, 2013 at 13:27 Comment(0)
E
0

I have made a function for that, you only call it in a batch program within needing to code more.

The working is basically the same as the others, as it's the best way to do it.
Here's the link where I have that function

Evangelin answered 16/7, 2020 at 10:57 Comment(0)
A
-1

To avoid blank line skipping just replace this:

echo !modified! >> %OUTTEXTFILE%

with this:

echo.!modified! >> %OUTTEXTFILE%
Archy answered 27/9, 2016 at 20:16 Comment(1)
This isn't an answer to the questionOdessaodetta
H
-7

If you have Ruby for Windows,

C:\>more file
bath Abath Bbath XYZbathABC

C:\>ruby -pne "$_.gsub!(/bath/,\"hello\")" file
hello Ahello Bhello XYZhelloABC
Hollins answered 11/3, 2011 at 14:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.