While other scripting languages have gained popularity, Perl remains a popular choice due to its robust text processing capabilities. It’s easy to create “one-liners,” or very short scripts, that can even replace standalone Unix utilities. Here are some tools you can create right from the command line.
Regex Matching to Replace grep
grep is one of the most useful tools in Linux to examine output. It searches text using regular expressions, a precise language that allows you to specify matches down to the character level. Perl is known for its regular expression matching abilities, so much so that a lot of other utilities and programming languages advertise “Perl-compatible” regular expressions.
It’s easy to set up a one-liner Perl version of grep:
perl -ne 'print if /PATTERN/'
Let’s walk through this. The -n option tells the Perl interpreter to assume that this loop already exists around the program:
while (<>) {
do_something
}
The -n means that Perl will take any input that comes from the standard input or from a filename. The greater-than and less-than symbolsis Perl’s filehandle operator. Perl will go through every line in the file and run the operations you’ve specified in the block. The pattern between the two forward slashes will be the regular expression you’re trying to match. See theperlrun page in the Perl documentationfor more info on Perl’s command-line options.
The -e will tell Perl not to look for a Perl source file, such as one that ends with .pl. This is what makes Perl one-liners possible. Putting this together, we can build a small replacement for the grep program. Let’s see how it works.
Suppose you wanted to find any running shells on the system. Since Linux shells typically end in sh, we can search for this pattern. To get the list of all running processes, you can use the command “ps aux” to get the list of running processes for all users and redirect the output into your one-liner with the “|” or pipe character.
We might start with just matching the pattern “sh”:
ps aux | perl -ne 'print if /sh/'
This will print any line that matches the pattern “sh” in the output of the ps program. We can also get more specific with character quantifiers. To match the “s” followed by an h:
ps aux | perl -ne 'print if /.sh/'
We can also specify any single character that contains “sh.” This will match things like “bash” or “zsh”
ps aux | perl -ne 'print if /.*sh/'
Make sure any actual Perl code in a Perl one-liner is in single quotes, so the shell won’t interpret them instead of Perl. If you don’t, you’ll get an error message instead.
Since many shell names end in “sh,” we can search for anything containing “sh” at the end of a word with the “\b” character class:
ps aux | perl -ne 'print if /.*sh\b/'
Not only will this work with redirected output, it will also work on files
perl -ne 'print if /.*sh/' example.txt
This will print any line containing “sh” in the file example.txt.
You can also replace the inverse grep, or grep -i, using the “unless” command in Perl:
perl -ne 'print unless /sh/'
Printing Fields to Replace awk
awk is another venerable Linux utility that’s useful for working through data organized in columns, such as processes or simple databases. A Perl one-liner can also go through this code quickly.
Suppose we wanted to show the user name and the program the user was running from the command ps aux, we’d write something like this:
ps aux | perl -ane 'print "$F[0] $F[10]\n"'
What the Perl code does is assume the classic “while ()” loop around the program, but it also splits the input into fields. The fields are stored in an array called “@F” where an array is identified by an “at” (@) symbol. To get at the values of the array, you prepend the name with a dollar sign, and the number of the field as a number, starting from 0 for the first element. Perl gets flak for the supposed messiness of using “sigils” like the dollar sign to identify variables, but it’s easy to understand once you know this convention.
Also, pay attention to the quoting. This Perl expression with the variables will need to be in double quotes within the single-quote expression to make sure the Perl interpreter sees it.
The example above will print the first column, $F[0], which is the user name, while $F[10] retrieves the path name of the executable associated with that process. This is how the Linux version of ps reports its output. If you’re using a BSD system, you might have to adjust it. A similar one-liner would work with any other program using data arranged this way.
You can use the -F switch to specify a pattern to split the lines on. For output separated by a colon, you’d use something like:
perl -F '/:/'
Search and Replace to Replace Sed
You might have run a search and replace operation using the s/old/new/ construction either in Vim or at the command line using the sed program. Since Perl’s regular expression search and replace function seems, ahem, “inspired” by this classic Unix utility, it’s easy to translate into a Perl one liner:
perl -pe "s/old/new/"
This will work both with input piped into it and at the command line by itself. Hopefully, if Randal Schwartz reads this, he won’t give me a “Useless Use of Cat” award. For example, to replace “dog” with “cat”
perl -pe "s/dog/cat"
You can try it on something like “I like petting my dog.”
The word “dog” will be changed to “cat.”
If you try this on a line like “My dog’s breath smells like dog food,” with more than one instance of the pattern you want to replace in the line, you might notice that only the first occurrence is replaced:
My cat's breath smells like dog food.
If your cat’s breath actually does smell like dog food, this would be sufficient. You can also replace every instance by appending the original “s/old/new” operator with “g” for “global.
Let’s make sure your cat’s breath smells like cat food:
perl -pe "s/dog/cat/g"
Now every instance of the pattern will br replaced when it appears in the line.
Sorting to Replace Sort
You might use the sort to sort standard input alphabetically. This is also easy to do with a one line
perl -e "print sort <>"
This will tell Perl to sort the standard input, which again includes any file specified from the command line, or piped in from another command, and sort the output by alphabetical order, or rather according to your system’s “locale” setting. In my case, it’s C.UTF-8. If your system is set up to use a different language, the lines might be sorted differently. On my system, lines with capital letters seem to be sorted first.
Removing Duplicates to Replace uniq
uniq is used in lists along with sort to remove duplicate entries. You can replicate the functionality with this one-liner:
perl -ne 'print if $_ ne $prev; $prev = $_'
This will compare the current line to the previous one and print it if they’re unequal. The “$_” variable is a shortcut for the current input line. While this one-liner demonstrates some Perl concepts, I would probably stick to uniq in practice, since it’s only four characters long.
You can even combine one-liners with pipes at the shell. Here’s an example to print unique items generated by a one-liner that picks out fields from the output mentioned earlier:
ps aux | perl -ane 'print "$F[0]\n"' | perl -ne 'print if $_ ne $prev; $prev = $_'
Replacing tr for Replacing Characters
While you saw the previous search and replace operator working on regular expressions, the tr command in Linux works on individual characters and character classes. Suppose you wanted to put a file in uppercase, so it looks like you were constantly shouting, you’d use this one-liner to replace tr:
T
perl -pe 'tr/a-z/A-Z/'
This will replace every lowercase character from a to z with its capital counterpart.
These one-liners should give you a taste of Perl’s text-processing power and show why the language still has some life left in it. You can do a lot with a little code in Perl.



