Perl tr/// Function

The tr/// function is used to transliterate a string.

The tr/// function is used in Perl to transliterate all occurrences found in a search list with the corresponding character in a replacement list. This function is a character by character translation and if you want to perform more complex operations you can use the s/// regex substitution operator instead. In Perl tr/// is known better as an operator rather than a function.

The syntax form of Perl tr/// is as follows:

tr/SEARCHLIST/REPLACEMENTLIST/cds
 
It replaces all the occurrences of the characters in SEARCHLIST with the characters in the REPLACEMENTLIST.  It returns the number of characters replaced or deleted. The transliteration table is built at compile time, so you can’t use interpolation either in SEARCHLIST or in REPLACEMENTLIST. If you need to use variables, you can use the eval function (see one of the examples shown below).   

The c , d , s are modifiers that add additional functionality to the tr/// operator:

  • c  - is used to specify that the SEARCHLIST character set is complemented
  • d  - is used to delete found but not replaced characters
  • s  - is used to specify that the sequences of characters that were transliterated to the same character are squashed down to a single instance of the character

The strings can be specified via the =~, !~ binding operators or $_ by default.  Please note that tr/// does not do regular expressions character classes such as \d.  

One character that has a special meaning to tr/// is the dot (-) and it indicates a range of characters (for example tr/A-C/a-c/).

The slash (/) has the meaning of a delimiter, because it separates the arguments of the tr/// operator. However, you can replace it with whatever sign of punctuation you want. The syntax changes a little if you use parentheses because they include the idea of containment.

For instance, the following syntax forms of the Perl tr/// function are equivalents and do the same thing (it replaces any lowercase character from a to f with digits from 2 to 7 and any character from g to z with the 7 digit):

$str =~ tr/a-z/2-7/;
$str =~ tr:a-z:2-7:;
$str =~ tr[a-z][2-7];
$str =~ tr(a-z)(2-7);
$str =~ tr<a-z><2-7>;
To illustrate how to use this operator, in the following articles I gave you several examples where a few of them include uppercase or lowercase conversions.

However, if you work with Unicode characters and you need to change your text in lowercase or uppercase, don’t use the Perl tr/// operator because it not pays attention to Unicode information. In this case you can use the \U sequence in a double quote string or the equivalent lc and uc functions.

The following example shows you how to use the tr/// operator with the =~ binding operator:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $string = 'one two three four five six seven';
$string =~ tr/a-z/A-Z/;
 
print "$string\n";
# it prints: ONE TWO THREE FOUR FIVE SIX SEVEN
This code will convert the content of the $string variable to uppercase.

If you want to count the number of the replaced characters returned by the tr/// operator, you can modify this code appropriately:

my $string = 'one two three four five six seven';
my $count;
$count = $string =~ tr/a-z/A-Z/;
 
print "$string\n";
# it prints: ONE TWO THREE FOUR FIVE SIX SEVEN
 
print "\$count = $count\n";
# it prints: $count = 27;
The $count variable will contain the number of the replaced characters returned by the tr/// operator.

If you want to keep the value of the input string unmodified and store the result in a new string, you can modify this code as follows:

my $str = 'one two three four five six seven';
my ($count, $newStr);
$count = ($newStr = $str) =~ tr/a-z/A-Z/;
 
print "\$str = $str\n";
# it prints: $str = one two three four five six seven
print "\$newStr = $newStr\n";
# it prints: $newStr = ONE TWO THREE FOUR FIVE SIX SEVEN
print "\$count = $count\n";
# it prints: $count = 27;
First, the content of the $str variable is copied in the $newStr variable and then the Perl tr/// operator acts against the $newStr variable. The number of the replaced characters will be assigned to the $count variable.

If you don’t supply a string variable to the Perl tr/// operator by using the =~ binding operator, $_ will be used instead. In the following example, the elements of an array will be converted in uppercase characters using a foreach loop and the tr/// operator:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my @array = qw(one two three four five six seven);
foreach (@array) {
  tr/a-z/A-Z/;
}
 
print "@array\n";
# it prints: ONE TWO THREE FOUR FIVE SIX SEVEN
First, @array is initialized with a few strings using the qw operator. The foreach loop will iterate through the elements of the array and at each iteration step:
 
  • each element is assigned in turn to $_
  • the tr/// operator acts against $_ and because $_ is an alias of the current element of the array, the array element will be modified in place

Finally, the array is printed.

If you prefer, you can replace the foreach block and write an one-line foreach loop instead:

tr/a-z/A-Z/ foreach (@array);

If the c modifier is used, than the SEARCHLIST character set is complemented. See the following example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = '123.95,44.32,27.77,221q23';
$str =~ tr/0-9/ /c;
print "$str\n";
# it prints: 123 95 44 32 27 77 221 23

The Perl tr/// operator will change all non-digits characters to single space.

The d modifier is used to delete any character specified in SEARCHLIST but not found in REPLACEMENTLIST. Here is an example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = 'aa bbb c dd eee ff mmmm rr';
$str =~ tr/a-z/1234/;
print "$str\n";
# it prints: 11 222 3 44 444 44 4444 44
 
# using the d modifier
$str = 'aa bbb c dd eee ff mmmm rr';
$str =~ tr/a-z/1234/d;
print "$str\n";
# it prints: 11 222 3 44
We want to replace all the characters from the a-z list with digits. Because the replacement list contains four characters only, the no matching characters are replaced by the last character found in the replacement list (i.e. the digit 4).

But if you use the d modifier, the found characters that are not replaced are deleted from the string (all others characters  than a,b,c,d will be deleted), as you can see in the above example.

The s modifier is used to remove the duplicate replaced characters. See the following example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = '123,,,95,,44,,32,,,,27....77';
$str =~ tr/,./,,/s;
print "$str\n";
# it prints: 123,95,44,32,27,77
Appending the s modifier to the Perl tr/// function has as effect the deleting of all the replaced characters that are duplicates.

You can use the c, d, s modifiers in your scripts as you need. The following example uses the c and s modifiers, you can use them in any order you want (i.e. cs or sc):

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = 'This  .  is  an 7example    9only';
$str =~ tr/A-Za-z/-/sc;
print "$str\n";
# it prints: This-is-an-example-only
The c modifier will replace all non alphabetical characters with the dash character and the s modifier will remove the replaced characters that are duplicates.

The transliteration table is built at compile time, so the tr/// operator doesn’t interpolates variables. If you use a code line as the following one:

$str =~ tr/$sl/$rl/;
the tr/// operator will replace character by character: $ to $, s to r, and l to l. I’m sure that this is not what you want.

If you want to use variables, either in SEARCHLIST or in REPLACEMENTLIST you can use the eval function. You can use the eval syntax form with an expression: it takes an expression as argument and treats it as Perl code, compiling and executing it. The appropriate result will be returned. If a fatal error arises, the $@ special variable will be set.

The following code snippet shows you how to use the tr/// operator with the eval function:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = 'one two three four five six seven';
my ($sl, $rl) = ('a-z', 'A-Z');
 
eval "\$str =~ tr/$sl/$rl/";
die $@ if $@;
 
print "$str\n";
# it prints: ONE TWO THREE FOUR FIVE SIX SEVEN
If you don’t want to bind the tr/// operator to a string, you can call it against $_:
 
eval "tr/$sl/$rl/";

Because the tr/// operator returns the number of replacements it made, you can use it to count the occurrences of a character in a string:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = 'This pencil is .... old. You can ..... it .....';
my $count = $str =~ tr/././;
 
print "\$count = $count\n";
# it prints: $count = 15
It counts the number of dots in the $str variable and stores that in the $count variable. (Well, if you didn’t guess the missing words, here is the answer: "This pencil is very old. You can throw it away.")

The Perl tr/// (translation) operator replaces all occurrences of the characters in SEARCHLIST with the corresponding characters in REPLACEMENTLIST. It has a very limited functionality but is faster than s/// regex substitution operator. Unlike the substitution operator, the translation operator does not use regular expressions for its search or replacement values.

The substitution operator allows you to make complex substitution using various pattern matching. For instance, using s/// with its g and e modifiers allows you to replace all occurrences of the found expression with the replacement text and evaluate the replacement as if it were a Perl statement:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $str = 'This pencil is very old.';
$str =~ s/(\w)/uc($1)/ge;
 
print "\$str = $str\n";
# it prints: $str = THIS PENCIL IS VERY OLD.
Because the e modifier was added to the s/// substitution operator, in its replacement area you can us the uc function. The g global modifier allows you to match all the words contained in the $str variable. The (\w)captures any word and stores it in the $1 special variable.