Gossamer Forum
Home : General : Perl Programming :

Search and Replace Text in Files (w/o backup?)

Quote Reply
Search and Replace Text in Files (w/o backup?)
perl -pi.bak -e "s/oldtext/newtext/g" *.txt

This works on my windows machine from the command line, but I don't want to the the back up file. Is there a way around it?

<edit>Well, crap. It didn't work on multiple files...
I've found many variations on this and none of them actually work.

Does anybody have a snippet of code for searching and replacing text in multiple files that they actually use on a regular basis?

I like this one (because I did it), but it keeps appending to the files for *each* occurance, so I know it's not quite right.

Code:
chdir('P:\Mike\JS') or die "cannot connect to P: \n";


@AllDTA = glob('*.js');
foreach $FileName (@AllDTA) {



open(NOTES, "<$FileName") or die "Could not open $FileName for reading\n";
while (<NOTES>) {
$notelines .= $_;
}
close(NOTES);

open(NOTES, ">$FileName") or die "Cannot find $FileName - no such file or invalid path\n";
select(NOTES);
$notelines =~ s/5508 Hwy/5716 Hwy/g;

print $notelines;

close(NOTES);

}

</edit>

Last edited by:

Watts: Jan 27, 2006, 9:13 AM
Quote Reply
Re: [Watts] Search and Replace Text in Files (w/o backup?) In reply to
Hi,

A grep maybe? Not quite sure what you're trying to do =)

I normally use this to do a search-and-replace (i.e when moving LSQL installs over, etc);

cd /path/to/admin
perl -p -i -e 's|\Q/old/path|/new/path|g' `grep -r -l '/path/to/change' .`

Hope that helps.

Cheers

Andy (mod)
andy@ultranerds.co.uk
Want to give me something back for my help? Please see my Amazon Wish List
GLinks ULTRA Package | GLinks ULTRA Package PRO
Links SQL Plugins | Website Design and SEO | UltraNerds | ULTRAGLobals Plugin | Pre-Made Template Sets | FREE GLinks Plugins!
Quote Reply
Re: [Andy] Search and Replace Text in Files (w/o backup?) In reply to
Thanks, I'll give it a whirl. I've got to change an address in a bunch of text files so I decided to try a "Perl" solution instead of doing it manually. However, the most popular solution (according to Google) doesn't work on my XP machine for some reason..

If I do at a command prompt (C:\Perl\bin)
perl -pi -e 's/5508 Hwy 290/5716 Hwy 290/g' *.js

then it complains:
can't find string terminator " ' " anywhere before EOF at -e line 1.

If I swap the -pi -e to read -e -pi then it doesn't complain, but it doesn't work either.

The very top example in this post works, but only on the first file. It doesn't loop thru subsequent files for some reason.

I also like the one I came up with, but I think I have my foreach and while parts screwed up, because it does the following:

Text in first file comes out correctly as:
Bob Jones

Text in second file comes out twice:
Bob Jones
Bob Jones

Text in third file comes out three times:
Bob Jones
Bob Jones
Bob Jones
Quote Reply
Re: [Watts] Search and Replace Text in Files (w/o backup?) In reply to
Hi,

Yeah, running "perl" from a cmd prompt in NT is a bit of a PITA (I have the same problem - mainly when trying to run MCPAN to install new modules).

I suggest, try this first;

perl -p -i -e 's|\Q/old/path|/new/path|g' `grep -r -l '/path/to/change' .`

..and see if that gives you the same "string terminator" error. If it does.. then I guess its not gonna work via cmd :(

Hope that helps.

Cheers

Andy (mod)
andy@ultranerds.co.uk
Want to give me something back for my help? Please see my Amazon Wish List
GLinks ULTRA Package | GLinks ULTRA Package PRO
Links SQL Plugins | Website Design and SEO | UltraNerds | ULTRAGLobals Plugin | Pre-Made Template Sets | FREE GLinks Plugins!
Quote Reply
Re: [Andy] Search and Replace Text in Files (w/o backup?) In reply to
Rats... it doesn't like the \Q

I'll hack around on mine and see what I come up with. I'll run it from a browser so it'll prompt you to enter the old text, new text, path, and file type.

I just suck at loops, but I guess I need to learn so this is a good place to start.

Thanks anyway.
Quote Reply
Re: [Watts] Search and Replace Text in Files (w/o backup?) In reply to
Solution

(add the "my" part in bold)

###############################

chdir('P:\Mike\JS') or die "cannot connect to P: \n";

@AllDTA = glob('*.js'); #type of file to search (.txt, .htm, etc.)

foreach $FileName (@AllDTA) {

my $notelines;

open(NOTES, "<$FileName") or die "Could not open $FileName for reading\n";
while (<NOTES>) {
$notelines .= $_;
}
close(NOTES);

open(NOTES, ">$FileName") or die "Cannot find $FileName - no such file or invalid path\n";
select(NOTES);

$notelines =~ s/123 Maple Street/456 Main Drive/g;

print $notelines;

close(NOTES);

}

#########################

This works if you save it to a perl file and run from the command prompt using ActivePerl. It will cruise through multiple files (in the same directory) and change the text as indicated. Which in my case was 798 javascript files.

.
Quote Reply
Re: [Watts] Search and Replace Text in Files (w/o backup?) In reply to
Code:
perl -Mstrict -pe 's/123 Maple Street/456 Main Drive/g' *.js

(You want strict so that the program fails before clobbering your files if you make a typo.)

Why doesn't this work? Because DOS (and Windows's DOS emulator) does not support interpolation or single quotes. When using a Unixish system, it is quite common to always use single quotes unless interpolation is needed. This is to avoid accidentally messing up your string by having special characters in a quote.

The sh equivalent to the cmd interpretation of that command is like
Code:
perl '-Mstrict' '-pe' "'s/123" 'Maple' 'Street/456' 'Main' "Drive/g'" *.js

beautiful.

@ARGV contains 'Maple', 'Street/456', 'Main', "Drive/g'", and everything in the current directory matching *.js... not exactly what you had hoped for.

So the following code will work best (and it will work on Unixish systems too because there are no special characters:
Code:
perl -Mstrict -pe "s/123 Maple Street/456 Main Drive/g" *.js



glob ('*.js'); is roughly equivalent to split (/\s+/, system ('dir *.js')); in Windows. Not only do you get a high overhead function (system), but you use the evil form of it that requires shell processing. The better form is like
Code:
opendir (DIR, 'some/path');
while ($file = readdir (DIR)) {
push (@files, $file) if ($file =~ /\.js$/);
}
closedir (DIR);

But looping through the files in a directory... only so that you can loop through them again a few lines later? Better to add the 'next unless' and keep it all in the 'while' loop.

The moral is not to use Windows if it can at all be helped Wink, or if it can't be, to be very careful about running commands that were initially written to be run on Unixish systems.