Globally replace text in several files: Difference between revisions
(Category:Text Processing) |
m (Category:Text processing) |
||
Line 266: | Line 266: | ||
{{omit from|PARI/GP|No real capacity for string manipulation}} |
{{omit from|PARI/GP|No real capacity for string manipulation}} |
||
[[Category:Text |
[[Category:Text processing]] |
||
[[Category:File System Operations]] |
[[Category:File System Operations]] |
Revision as of 18:23, 17 June 2011
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<stdio.h>
- include<stdlib.h>
- include<string.h>
char*ri="Goodbye London!",*ro="Hello New York!";
void die(char*s){
perror(s); exit(1);
}
char*loadFile(char*s){
int x; FILE*f=fopen(s,"rb"); if(!f) die("fopen failed"); fseek(f,0,SEEK_END); s=malloc((x=ftell(f))+1); if(!s) die("malloc failed"); rewind(f); fread(s,1,x,f); s[x]=0; fclose(f); return s;
}
void saveFile(char*fn,char*s){
FILE*f=fopen(fn,"wb"); if(!f) die("fopen"); fwrite(s,1,strlen(s),f); fclose(f);
}
void stringReplace(char*s,char*a,char*b){
char*p; int sl=strlen(s)+1,bl=strlen(b); int oa=0,ob=0; signed d=strlen(a)-bl; if(d<0) oa=-d; else ob=d; while((p=strstr(s,a))!=0){ memmove(p+oa,p+ob,sl-(p-s)-d); memcpy(p,b,bl); }
}
void process(char*f){
char*s=loadFile(f); stringReplace(s,ri,ro); saveFile(f,s);
}
int main(int argc,char**argv){
if(argc) while(--argc) process(*++argv); return 0;
}</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>
D
<lang d>import std.file, std.array;
void main() {
auto from = "Goodbye London!", to = "Hello, New York!"; foreach (fn; "a.txt b.txt c.txt".split()) { write(fn, replace(cast(string)read(fn), from, to)); }
}</lang>
Icon and Unicon
This example uses the Unicon stat function. It can be rewritten for Icon to aggregate the file in a reads loop. <lang Icon>procedure main() globalrepl("Goodbye London","Hello New York","a.txt","b.txt") # variable args for files end
procedure globalrepl(old,new,files[])
every fn := !files do
if s := reads(f := open(fn,"bu"),stat(f).size) then { writes(seek(f,1),replace(s,old,new)) close(f) } else write(&errout,"Unable to open ",fn)
end
link strings # for replace</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>