Generalised Search-And-Replace

Specify patterns on the command line, but without worrying about quoting or escaping anything. Do search-and-replace over multiple files, at once. Do one thing, but do it well.    #perl #script #search #replace    [Source code]

My text editor of choice, vim, is pretty good at searching and replacing text. On occasion, however, it seems lacking, usually for one of two reasons:

Now, at this stage, the cynical person will probably retort that I need a new text editor… but let us not listen to the naysayers! (Because what they actually mean is that I should be using an Integrated Development Environment (IDE), which I don’t do because… they all suck!)

What I did instead was to write a small Perl script, that basically takes an initial text, a replacement text, and replaces the former with the latter, either on a specific file, or in all files within a given directory, ending in a specific extension. In more detail, the script can be invoked in the following two ways (this is also shown when invoking the script with -h):

$ /path/to/script -i '<original text>' -o '<replacement text>' -f <file name>
$ /path/to/script -i '<original text>' -o '<replacement text>' -d <dir name> -t <file extension>

The single most important thing to remember, when using this script, is the following:

To avoid involuntary Shell escaping, ALWAYS ENCLOSE ORIGINAL AND REPLACEMENT TEXTS IN **SINGLE** QUOTES!!

Doing that ensures that both <original text> and <replacement text> can contain spaces, backslashes, or other usually “problematic” characters, without need to quote/escape anything—the script will just work.

The first form will do the search/replace operation in the file named <file name>, while the second will do it in all files in directory <dir name>, having the extension <file extension>. And this is basically it.

The -B option. This extra nice to have is easy to explain with an example. Suppose you call the script with -i 'foo' -o 'bar'. By default, it will replace (for example) foo_1 with bar_1. To avoid this, i.e., to only replace “whole words”, pass the -B option (for “word boundary”): then, the replacing will only take place when the string “foo” is surrounded by neither alphanumeric characters, nor underscores (_).1 So in the previous example, foo_1 would not be replaced with bar_1—but foo bar would become bar bar.

Setup

Take the code, save it in a file with .pl extension (this is customary for Perl scripts), and give it executable permissions (chmod +x filename.pl). This last part is optional, but if you don’t do it, then you can only invoke the script like this: $ perl filename.pl, but not like this: $ ./filename.pl. Then just use the script as explained above.

Last, but assuredly not least, the customary advice: using this script can result in large changes which, in case of errors, can be hard to undo. Hence, always backup your data before using it!

May 21, 2022.

* * *

[Update] May 28, 2022. The previous version, when modifying files in a directory, gave the total count of files found, not the total count of files that will actually be modified. This has now been fixed.