← Весь справочник

tr

Посимвольная замена и удаление символов — регистр, переводы строк, лишние пробелы

tr (translate) работает с отдельными символами, а не со строками и не с регулярками: заменяет символы из одного набора соответствующими символами из другого, удаляет или сжимает повторы. Читает только стандартный ввод и пишет в стандартный вывод.

Синтаксис

tr [опции] 'набор1' 'набор2' < файл     # замена
tr -d [опции] 'набор1' < файл           # удаление
tr -s 'набор1' < файл                   # сжатие повторов

При замене первый символ набор1 превращается в первый символ набор2, второй — во второй и так далее.

Опции

ОпцияЧто делает
-dудалить символы из набор1
-sсжать подряд идущие одинаковые символы из последнего указанного набора в один; выполняется после замены или удаления
-c (-C)взять дополнение набор1 — все символы, кроме перечисленных
-tпри замене обрезать набор1 до длины набор2 (вместо того чтобы удлинять набор2)

Как записывать наборы

ЗаписьЧто значит
abcсами символы
a-z, 0-9диапазон по порядку кодов
[:lower:] [:upper:]строчные / заглавные буквы; в паре дают смену регистра
[:digit:] [:xdigit:]цифры / шестнадцатеричные цифры
[:alpha:] [:alnum:]буквы / буквы и цифры
[:space:] / [:blank:]все пробельные, включая \n / только пробел и табуляция
[:punct:] [:cntrl:] [:print:] [:graph:]пунктуация / управляющие / печатные с пробелом / печатные без пробела
\n \t \r \\перевод строки, табуляция, возврат каретки, обратный слэш
\NNNсимвол с восьмеричным кодом, например \000 — нулевой байт
[x*] / [x*5]во втором наборе: x столько раз, сколько нужно до длины первого / 5 раз

Примеры

# в верхний регистр
echo 'hello' | tr 'a-z' 'A-Z'
echo 'hello' | tr '[:lower:]' '[:upper:]'

# сжать повторяющиеся пробелы в один
echo 'a  b   c' | tr -s ' '

# удалить все цифры / оставить только цифры
echo 'a1b2c3' | tr -d '0-9'
echo 'a1b2c3' | tr -cd '0-9'

# разделитель в перевод строки — каждое значение на своей строке
echo 'a:b:c' | tr ':' '\n'
echo "$PATH" | tr ':' '\n'

# склеить строки в одну через пробел
printf 'one\ntwo\nthree\n' | tr '\n' ' '

# убрать виндовые \r в конце строк
printf 'line\r\n' | tr -d '\r' | od -c

# заменить несколько символов разом: l → 0, o → 1
echo 'hello' | tr 'lo' '01'

# всё, что не буквы и не цифры, — в подчёркивание, повторы сжать
echo 'Hello, World! 2024' | tr -cs '[:alnum:]' '_'

# разбить текст на слова: каждое на своей строке
echo 'one two  three' | tr -s '[:space:]' '\n'

# нулевые байты в переводы строк (например, /proc/*/environ)
tr '\0' '\n' < /proc/1/environ | head -n 3

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

Подводные камни

  • Это не замена строк. tr 'abc' 'xyz' меняет a→x, b→y, c→z по отдельности, где бы они ни стояли. Чтобы заменить слово целиком, нужен sed.
  • Короткий второй набор дополняется последним символом. echo abc | tr abc x даст xxx. С -t лишние символы первого набора просто не трогаются: echo abc | tr -t abc x даст xbc.
  • Файл передаётся только через <. tr a b файл — ошибка extra operand.
  • Квадратные скобки — обычные символы. tr '[a-z]' '[A-Z]' работает лишь потому, что [ переходит в [. Без кавычек [a-z] может раскрыть оболочка, если в каталоге есть файл из одной буквы.
  • Дефис между символами — диапазон. Чтобы заменить сам дефис, ставь его последним в наборе: tr 'a-' 'x_'. Набор, который начинается с - и буквы ('-x'), tr примет за опцию — пиши tr -- '-x' '_y'.
  • Многобайтовые символы tr не понимает. GNU tr работает с байтами, поэтому tr 'а-я' 'А-Я' портит кириллицу при любой локали. Для неё используй sed (s/.*/\U&/) или awk (toupper) в UTF-8-локали.

См. также

sed · cut · iconv · wc