One of the most forgotten functions in Perl is the ‘tr‘ or translate function.
I say forgotten, because other than changing the case of letters from upper to lower, most programmers don’t think much of the ‘tr‘ function. By definition:

tr/SEARCHLIST/REPLACEMENTLIST/[c][d][s]
y/SEARCHLIST/REPLACEMENTLIST/[c][d][s]

This function translates all occurrences of the characters found in the search list to the corresponding character in the replacement list.

In general use we see:

$value =~ tr/A-Z/a-z/;

which simply translated all upper-case characters in $value into lower-case characters. In each field, a range of characters is specified. “A-Z” for the SEARCHLIST and “a-z” for the REPLACEMENTLIST.

Direct or Complement?

What is often overlooked or forgotten is that lists can be specified directly or as a complement. In this instance “complement” means everything except. So for instance /A-Za-z0-9/ refers to all alphanumeric characters. As a complement it means all non-alphanumeric characters. So, for example, if you want to disallow punctuation and other non-printing characters, you can translate them to spaces or even just delete them.

$letters =~ tr/A-Za-z0-9/ /c;
$letters =~ tr/A-Za-z0-9//cd;
$letters =~ tr/A-Za-z0-9/ /cs;

The first example translates all non-alphanumerics to spaces, and the second example deletes them from the variable $letters. The third example uses the squeeze option (s) to combine the translated letters so that consecutive translated letters of the same destination translation are compressed together into a single character. This takes what would normally be multiple spaces, or multiple occurrences of any single letter and combines them to a single space. If $letters contained the string “ABC::D,E,(F+G)/H” the result would be “ABC space space D space E space space F space G space space H”. With the (s) option, each occurrence of “space space” becomes a single “space”.

Counting Characters

One other forgotten use of the ‘tr’ function is that it also returns a value which is the count of translations made to individual characters. Thus, it can be used as a quick count, even if it translates a given character into itself.

$plus = tr/+/+/;
$letters = tr/A-Za-z/A-Za-z/;

The first example counts the number of plus (+) characters in the default string “$_“, and the second example counts the number of letters in “$_“. Please notice the difference in these examples. The first set of examples is using “=~” which says to apply the function to the variable on the left of the “=~”. The last set of examples uses a simple “=” to assign the count of translated characters to the variables “$plus” and “$letters“.