Globally replace text in several files
You are encouraged to solve this task according to the task description, using any language you may know.
The task is to replace every occuring instance of a piece of text in a group of text files with another one. For this task we want to replace the text "Goodbye London!" with "Hello New York!" for a list of files.
AutoHotkey
<lang AutoHotkey>SetWorkingDir %A_ScriptDir% ; Change the working directory to the script's location listFiles := "a.txt|b.txt|c.txt" ; Define a list of files in the current working directory loop, Parse, listFiles, | { ; The above parses the list based on the | character fileread, contents, %A_LoopField% ; Read the file fileDelete, %A_LoopField% ; Delete the file stringReplace, contents, contents, Goodbye London!, Hello New York!, All ; replace all occurrences fileAppend, %contents%, %A_LoopField% ; Re-create the file with new contents } </lang>
C++
<lang c++>#include <fstream>
- include <iterator>
- include <boost/regex.hpp>
- include <string>
- include <iostream>
int main( int argc , char *argv[ ] ) {
boost::regex to_be_replaced( "Goodbye London\\s*!" ) ; std::string replacement( "Hello New York!" ) ; for ( int i = 1 ; i < argc ; i++ ) { std::ifstream infile ( argv[ i ] ) ; if ( infile ) {
std::string filetext( (std::istreambuf_iterator<char>( infile )) , std::istreambuf_iterator<char>( ) ) ; std::string changed ( boost::regex_replace( filetext , to_be_replaced , replacement )) ; infile.close( ) ; std::ofstream outfile( argv[ i ] , std::ios_base::out | std::ios_base::trunc ) ; if ( outfile.is_open( ) ) { outfile << changed ; outfile.close( ) ; }
} else
std::cout << "Can't find file " << argv[ i ] << " !\n" ;
} return 0 ;
}</lang>
J
If files
is a variable with the desired list of file names:
<lang j>require'strings' (1!:2~rplc&('Goodbye London!';'Hello New York!')@(1!:1))"0 files</lang>
Lua
<lang lua>filenames = { "f1.txt", "f2.txt" }
for _, fn in pairs( filenames ) do
fp = io.open( fn, "r" ) str = fp:read( "*all" ) str = string.gsub( str, "Goodbye London!", "Hello New York!" ) fp:close()
fp = io.open( fn, "w+" ) fp:write( str ) fp:close()
end</lang>
Perl
<lang bash>perl -pi -e "s/Goodbye London\!/Hello New York\!/g;" a.txt b.txt c.txt</lang>
PicoLisp
<lang PicoLisp>(for File '(a.txt b.txt c.txt)
(call 'mv File (tmp File)) (out File (in (tmp File) (while (echo "Goodbye London!") (prin "Hello New York!") ) ) ) )</lang>
PureBasic
<lang PureBasic>Procedure GRTISF(List File$(), Find$, Replace$)
Protected Line$, Out$, OutFile$, i ForEach File$() fsize=FileSize(File$()) If fsize<=0: Continue: EndIf If ReadFile(0, File$()) i=0 ; ; generate a temporary file in a safe way Repeat file$=GetTemporaryDirectory()+base$+"_"+Str(i)+".tmp" i+1 Until FileSize(file$)=-1 i=CreateFile(FileID, file$) If i ; Copy the infile to the outfile while replacing any needed text While Not Eof(0) Line$=ReadString(0) Out$=ReplaceString(Line$,Find$,Replace$) WriteString(1,Out$) Wend CloseFile(1) EndIf CloseFile(0) If i ; If we made a new file, copy it back. CopyFile(file$, File$()) DeleteFile(file$) EndIf EndIf Next
EndProcedure</lang> Implementation
NewList Xyz$() AddElement(Xyz$()): Xyz$()="C:\\a.txt" AddElement(Xyz$()): Xyz$()="C:\\b.txt" AddElement(Xyz$()): Xyz$()="D:\\c.txt" GRTISF(Xyz$(), "Goodbye London", "Hello New York")
Python
From Python docs. (Note: in-place editing is not supported on Windows 8.3 operating systems).
<lang python>import fileinput
for line in fileinput.input(inplace=True):
print(line.replace('Goodbye London!', 'Hello New York!'), end=)
</lang>
Ruby
Like Perl:
ruby -pi -e "gsub('Goodbye London!', 'Hello New York!')" a.txt b.txt c.txt
Tcl
<lang tcl>package require Tcl 8.5 package require fileutil
- Parameters to the replacement
set from "Goodbye London!" set to "Hello New York!"
- Which files to replace
set fileList [list a.txt b.txt c.txt]
- Make a command fragment that performs the replacement on a supplied string
set replacementCmd [list string map [list $from $to]]
- Apply the replacement to the contents of each file
foreach filename $fileList {
fileutil::updateInPlace $filename $replacementCmd
}</lang>
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT files="a.txt'b.txt'c.txt"
BUILD S_TABLE search = ":Goodbye London!:"
LOOP file=files
ERROR/STOP OPEN (file,WRITE,-std-) ERROR/STOP CREATE ("scratch",FDF-o,-std-) ACCESS q: READ/STREAM/RECORDS/UTF8 $file s,aken+text/search+eken ACCESS s: WRITE/ERASE/STREAM/UTF8 "scratch" s,aken+text+eken LOOP READ/EXIT q IF (text.ct.search) SET text="Hello New York!" WRITE/ADJUST s ENDLOOP ENDACCESS/PRINT q ENDACCESS/PRINT s ERROR/STOP COPY ("scratch",file) ERROR/STOP CLOSE (file)
ENDLOOP ERROR/STOP DELETE ("scratch") </lang>