swapcase with the tr command
Published: 2022-04-01
Want to easily swap the case of some string on the *nix command line? The tr
command can do that!
You may already know the tr
command can switch lowercase to uppercase
$ echo "HI there" | tr '[:lower:]' '[:upper:]'
HI THERE
Or uppercase to lowercase
$ echo "HI there" | tr '[:lower:]' '[:upper:]' | tr '[:upper:]' '[:lower:]'
hi there
But we can take it further and tell tr
not only switch all lowercase to uppercase but all uppercase to lowercase in one transform!
$ echo "HI there" | tr '[:lower:][:upper:]' '[:upper:][:lower:]'
hi THERE
And because we’re using character classes and not simply a-zA-Z
that means unicode letters work as well.
$ echo "CAfé" | tr "[:lower:][:upper:]" "[:upper:][:lower:]"
caFÉ
This works because the arguments to tr
are a paired list of transforms. Each character in string1 (the first argument) will be replaced with the corresponding index of the character from string2 (the second argument)
$ echo crab | tr abc ABC
CrAB
The above command has abc
for the first string and ABC
for the second. That means tr
will pair them up like so
a => A
b => B
c => C
Having tr
perform a swapcase means making those strings include both uppercase and lowercase characters. If we were to pick randomly from the translation pairs it could look like this.
P => p
k => K
X => x
x => X
W => w
M => m
F => f
Why do this? Well for me I wanted a list of lowercase letters, uppercase letters, and numbers. printable-ascii
can easily provide me with that list but I wanted to go from lowercase to uppercase to numbers. But ASCII order has uppercase first.
$ printable-ascii --letters --digits --compact
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
I could tell printable-ascii
more explicitly how to order the output by manually defining the ranges in the order I want
$ printable-ascii --range a-z --range A-Z --digits --compact
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
But the tr
command can easily do that work for me. And since I’m dealing explicitly with ASCII I can simply use a-zA-Z
$ printable-ascii --letters --digits --compact | tr A-Za-z a-zA-Z
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789