Search and replace is such a common task that it should be a tool that’s in every command line script author’s toolbox.
There are probably endless solutions to the problem.
I’ve put together my standard methods for tackling the problem, with Perl.
You can also use Python, of course, as well as other tools like sed
.
Use Models
In most of the following discussion, I’m just replacing ‘foo’ with ‘bar’.
However ‘foo’ can be ANY regular expression.
The dummy situation I’m going to set up is this.
I’ve got a file named example.txt
. It looks like this:
foo foo fiddle foo
and baz too, as well as foo
I realize that I want to replace ‘foo’ with ‘bar’.
I’d like to be able to have a script that runs in a way that I can either pipe the contents of the file into the script, or just give a file name to the script, like this:
cat example.txt | perl <something>
perl <something> example.txt
Now, I may or may not want to have the script modify the file in place.
If not, then the second example above would just print the modified contents.
I also may want to make a backup of example.txt first.
We can all of those things, as I’ll show below.
There are lots of ways to implement this in Perl.
On the Command Line
The following are all roughly equivalent:
cat example.txt | perl -pe 's/foo/bar/g;'
cat example.txt | perl -ne 's/foo/bar/g;print'
cat example.txt | perl -e 'while (<>){s/foo/bar/g;print;}'
cat example.txt | perl -e 'while (<>){$_ =~ s/foo/bar/g;print;}'
perl -pe 's/foo/bar/g;' example.txt
perl -ne 's/foo/bar/g;print' example.txt
perl -e 'while (<>){s/foo/bar/g;print;}' example.txt
perl -e 'while (<>){$_ =~ s/foo/bar/g;print $_;}' example.txt
flags used
- -e : execute the code on the command line
- -n : wrap everything in
while (<>){ [code here] }
- -p : wrap everything in
while (<>){ [code here]; print; }
As a Script
Of course, you don’t have to use the ‘-e’ flag.
You can stick the script in a file.
The following scripts are equivalent:
#!/usr/bin/perl
while (<>) {
$_ =~ s/foo/bar/;
print $_;
}
#!/usr/bin/perl
while (<>) {
s/foo/bar/;
print;
}
#!/usr/bin/perl -n
s/foo/bar/;
print;
#!/usr/bin/perl -p
s/foo/bar/;
Changing files in place
Perl also allows changing the files in place, with the addition of the ‘-i’ flag, usually used as ‘-i.bak’ to make backup copies of the original:
perl -pi.bak -e 's/foo/bar/g;' example.txt