tr — Translate, Delete and Squeeze Characters

Practical guide to tr — translate, delete or squeeze characters from standard input. The filter for character-level transformations in shell pipelines.

tr (translate) is the filter for character-level transformations in the shell – it reads from standard input, replaces, deletes or squeezes individual characters, and writes the result to standard output. Unlike sed, tr works not with patterns but with character sets: you give it a source and a target set, and it maps them onto each other character by character. POSIX character classes such as [:upper:] or [:digit:] cover whole groups, and with -d, -s and -c you delete, condense or invert the selection. tr does not take filenames – it lives exclusively in the pipe.

Character Translation

tr '<set1>' '<set2>' — Replace characters in set1 with corresponding characters in set2.

echo 'hello' | tr 'aeiou' 'AEIOU'

tr 'a-z' 'A-Z' — Convert lowercase to uppercase.

echo 'hello world' | tr 'a-z' 'A-Z'

tr 'A-Z' 'a-z' — Convert uppercase to lowercase.

echo 'HELLO' | tr 'A-Z' 'a-z'

tr '[:lower:]' '[:upper:]' — Convert lowercase to uppercase using POSIX character classes.

cat file.txt | tr '[:lower:]' '[:upper:]'

tr '<char>' '<char>' — Replace a single character with another.

echo '2024/01/15' | tr '/' '-'

tr ' ' '\n' — Replace spaces with newlines (one word per line).

echo 'one two three' | tr ' ' '\n'

tr '\n' ' ' — Replace newlines with spaces (join lines into one).

cat list.txt | tr '\n' ' '

tr ',' '\t' — Convert commas to tabs (CSV to TSV).

cat data.csv | tr ',' '\t' > data.tsv

tr '\t' ',' — Convert tabs to commas (TSV to CSV).

cat data.tsv | tr '\t' ',' > data.csv

Deleting Characters

tr -d '<chars>' — Delete all occurrences of the specified characters.

echo 'Hello, World!' | tr -d ',!'

tr -d '[:digit:]' — Remove all digits.

echo 'abc123def456' | tr -d '[:digit:]'

tr -d '[:alpha:]' — Remove all letters (keep digits, punctuation, etc.).

echo 'abc123def456' | tr -d '[:alpha:]'

tr -d '[:space:]' — Remove all whitespace (spaces, tabs, newlines).

echo '  hello   world  ' | tr -d '[:space:]'

tr -d '\n' — Remove all newlines (join all lines).

cat file.txt | tr -d '\n'

tr -d '\r' — Remove carriage returns (fix Windows line endings).

cat windows.txt | tr -d '\r' > unix.txt

tr -d '[:punct:]' — Remove all punctuation characters.

echo 'Hello, World! How are you?' | tr -d '[:punct:]'

Squeezing Repeats

tr -s '<chars>' — Squeeze repeated characters into a single occurrence.

echo 'heeello' | tr -s 'e'

tr -s ' ' — Collapse multiple spaces into a single space.

echo 'too    many    spaces' | tr -s ' '

tr -s '\n' — Remove blank lines (squeeze consecutive newlines).

cat file.txt | tr -s '\n'

tr -s '[:blank:]' — Squeeze all horizontal whitespace (spaces and tabs).

cat messy.txt | tr -s '[:blank:]'

tr -s ' ' '\t' — Squeeze multiple spaces and convert to a single tab.

ps aux | tr -s ' ' '\t'

Complement

tr -cd '<chars>' — Delete all characters EXCEPT the specified ones.

echo 'abc123def456' | tr -cd '[:digit:]\n'

tr -cd '[:alnum:]\n' — Keep only alphanumeric characters and newlines.

echo 'Hello, World! #123' | tr -cd '[:alnum:]\n'

tr -cd '[:print:]' — Remove all non-printable characters.

cat binary-mixed.txt | tr -cd '[:print:]\n'

tr -c '[:alnum:]' '_' — Replace all non-alphanumeric characters with underscores.

echo 'Hello World! @2024' | tr -c '[:alnum:]\n' '_'

Character Classes

[:alpha:] — All letters (a-z, A-Z).

tr -d '[:alpha:]'

[:digit:] — All digits (0-9).

tr -d '[:digit:]'

[:alnum:] — All letters and digits.

tr -cd '[:alnum:]'

[:upper:] / [:lower:] — Uppercase / lowercase letters.

tr '[:upper:]' '[:lower:]'

[:space:] — All whitespace (space, tab, newline, etc.).

tr -d '[:space:]'

[:blank:] — Horizontal whitespace only (space and tab).

tr -s '[:blank:]'

[:punct:] — All punctuation characters.

tr -d '[:punct:]'

[:print:] — All printable characters (including space).

tr -cd '[:print:]'

Common Patterns

tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c <n> — Generate a random alphanumeric string of n characters.

tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 32; echo

echo '<text>' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd '[:alnum:]-' — Create a URL slug from text.

echo 'Hello World Blog Post' | tr '[:upper:]' '[:lower:]' | tr ' ' '-'

cat <file> | tr -s ' ' '\n' | sort | uniq -c | sort -rn — Word frequency count: split words, sort, count, sort by frequency.

cat article.txt | tr -s ' ' '\n' | sort | uniq -c | sort -rn | head -20

echo '<ROT13>' | tr 'A-Za-z' 'N-ZA-Mn-za-m' — ROT13 encode/decode a string.

echo 'Hello World' | tr 'A-Za-z' 'N-ZA-Mn-za-m'

cat <file> | tr -cs '[:alpha:]' '\n' — Extract words only (one per line), removing all non-alphabetic characters.

cat mixed.txt | tr -cs '[:alpha:]' '\n'

Conclusion

tr is small, fast and surprisingly versatile – ideal for tasks such as changing case, cleaning up Windows line endings (tr -d '\r'), condensing whitespace or splitting text into word lists. Keep its quirks in mind, though: tr always replaces character by character, never whole strings – for multi-character search-and-replace you need sed. The literal \n and \t must appear inside the respective argument and are interpreted by tr itself. tr only partially handles multibyte (UTF-8) characters, because it operates byte by byte; for umlauts and special characters it is therefore not always the right choice.

Further Reading

  • sed – stream editor for pattern-based search and replace of whole strings
  • cut – extract fields, characters or byte ranges from lines
  • paste – merge lines of several files column by column