Undoubtedly one of the most frequent tasks a system administrator, or developer, faces involves making inline changes to a file or set of files. This can range from the very complex edit to the very trivial.

Let’s say you have a series of PHP pages in your web site that access your MySQL server. What happens if you need to change the name of your MySQL server? Would you go into each file individually, search for the line (or lines) of code to edit and save the file? This can be tedious, error-prone and time consuming.

The ’sed’ (string editor) command is often used to accomplish this, where sed is passed a file name and a regular expression for the string substitutions. Output from sed is sent to standard output (usually the terminal) which means that you must redirect it to another file and then copy the new file over the original. This effectively changes the original but requires a lot of excess steps. There’s got to be a better way, right? Yes, ‘perl’ can do it in one shot –

SysAdmin Mantra

A good sysadmin is a lazy sysadmin.

Enter ‘Perl Pie’

I forget who first introduced me to the concept of ‘perl -p -i -e’ (or ‘perl -pi -e’). This has become such a mainstay of my practice that I often mention it to people assuming that everyone knows of such things. Basically, ‘Perl Pie’ is a one-line perl program that does inline edits to your file given a regular expression (preserving file ownership and permissions — a topic that I didn’t discuss in the ’sed’ example above). The syntax should look familiar to anyone who’s used ’sed’ or regular expressions.

perl -p -i -e 's/original text string/replacement string' foo

Note: perl uses the same regex syntax as sed, making this an easy concept to remember

But Wait, I’ve got a ton of files to edit

There are numerous ways to accomplish editing multiple files, but they all share some basic principals:

  1. Find a list of files matching your change criteria
  2. With each file, apply the ‘Perl Pie’

Most GNU/Linux sysadmins are familiar with the Bash shell. Here’s a simple example that changes all of those PHP pages we talked about earlier. This example also involves the ‘find’ and ‘grep’ commands:

$ for filename in $( find . -type f -name '*.php' -exec grep -q '$db=OLDMYSQLSERVER' '{}' ';' -print );
do
   perl -p -i -e 's/$db=OLDMYSQLSERVER/$db=NEWMYSQLSERVER/g' $filename
done