Алексей Дмитриев, 12 декабря 2008

HuMan: tr

Команда tr

Команда tr служит для перевода (замены) выбранных символов в другие символы или удаления их.

В отличие от большинства других программ командной строки, команда tr не принимает имен файлов в качестве аргумента. Ввод команды tr осуществляется или со стандартного ввода, или с вывода других программ путем перенаправления.

Вот общий синтаксис команды tr:

tr [опция] набор1 [набор2]

Позиции в квадратных скобках не являются обязательными.

Команде tr требуется минимум один аргумент, а принимается максимум два. Первый аргумент, называемый набор1 перечисляет символы, подлежащие замене или удалению. Второй аргумент, набор2, перечисляет символы, которые должны заменить символы из набора1.

Команда tr без опций заменит символы из набора1 символами из набора 2.

Азы команды tr

В следующем примере, каждая буква a будет заменена буквой b:

$ tr a b

Затем следует нажать Enter и команда будет готова к приему текста:

$ tr a b  [Enter]
abracadabra

Когда текст введен, снова следует нажать Enter:

$ tr a b
abracadabra
bbrbcbdbbrb

Если снова нажать Enter, то можно продолжить ввод текста:

$ tr a b
abracadabra
bbrbcbdbbrb


caramba

Снова нажать Enter:

$ tr a b
abracadabra
bbrbcbdbbrb


caramba
cbrbmbb

И так далее. Когда нужно выйти из программы, нажимаем Ctrl+c.

Тут самое место рассказать, что программа tr понимает русский язык (по крайней мере правильно сделанную локализацию в UTF-8):

$ tr я ё
является
ёвлёетсё

Работа с файлами

Когда требуется обработать текст из файла, используем перенаправление ввода:

$ tr a b < file1.txt

Где значок < является оператором перенаправления ввода.

Что касается вывода команды tr, то гораздо удобнее иметь его в файле, чем на экране монитора, поэтому воспользуемся также оператором вывода (>):

$ tr a b < file1.txt > file2.txt

Если файл file2.txt не существует, то он будет создан. Если существует, то будет стерт и переписан.

Внимание: Остерегайтесь направлять вывод в тот же файл, откуда производился ввод:

$ tr a b < file1.txt > file1.txt

В этом случае весь текст в файле file1.txt исчезнет, включая вывод команды tr.

Чтобы избежать переписывания файла file2.txt следует применить добавляющий оператор перенаправления (>>):

$ tr a b < file1.txt >> file2.txt

В этом случае, если файл file2.txt не существует, то он будет создан, а если существует, то новый текст будет дописан в конец файла. Этим же способом можно дописать измененный текст в исходный файл:

$ tr a b < file1.txt >> file1.txt

Кроме метода перенаправления ввода/вывода, можно воспользоваться программными каналами (pipes), знаком которых является вертикальная черта (|):

$ cat file1.txt | tr a b > file2.txt

В этом примере вывод команды cat (которая прочтет файл file1.txt) будет передан на ввод команде tr (которая поменяет буквы), а после изменения будет записан в файл file2.txt.

Возможности команды tr

Понятно, что возможности команды tr не ограничиваются заменой одной буквы. Команда может заменять любое количество указанных символов на другие символы. В этом случае каждый из наборов символов заключается в квадратные скобки, а скобки, в свою очередь, в кавычки; безразлично, двойные или одинарные.

'[набор1]' '[набор2]' или "[набор1]" "[набор2]"

В наборе1 один подряд перечисляются символы, подлежащие замене, а в наборе2 - в соответствующем порядке символы, которые их должны заменить:

$ echo cheer | tr '[abcdefghijklmnopqrstuvwxyz]' '[hijklmnopqrstuvwxyzabcdefg]'
jolly

Для современных версий (у меня, например, tr GNU coreutils 5.97) все эти квадратные скобки и кавычки не обязательны, можно просто перечислять символы:

$ echo cheer | tr abcdefghijklmnopqrstuvwxyz hijklmnopqrstuvwxyzabcdefg
jolly

Работает не хуже.

Если буквы идут по алфавиту, то можно не перечислять их все, а указать диапазон при помощи черточки, например a-z. Этим часто пользуются для перевода символов из нижнего в верхний регистр и наоборот:

$ echo lower_case | tr '[a-z]' '[A-Z]'
LOWER_CASE

Кроме того, команда умеет удалять символы, перечисленные в наборе1, заменять повторяющиеся символы одиночными и кое-что еще.

Условные обозначения

Команда tr также оперирует с управляющими символами и прочими элементами форматирования. Большинство из них пишутся как есть. Но есть и условные обозначения. Некоторые начинаются обратным слэшем (\):

  • \nnn -- символ с восьмеричным значением nnn
  • \xnn -- символ с шестнадцатеричным значением nn
  • \\ -- обратный слэш
  • \a -- звуковой сигнал
  • \b -- backspace (обратный ход с забоем символа)
  • \f -- перевод страницы
  • \n -- новая строка
  • \r -- возврат каретки
  • \t -- горизонтальная табуляция
  • \v -- вертикальная табуляция
  • \E -- escape
  • ЗНАК1-ЗНАК2 -- все знаки от ЗНАК1 до ЗНАК2 в порядке возрастания. ЗНАК1 должен предшествовать по порядку возрастания ЗНАКУ2.
  • [ЗНАК1-ЗНАК2] -- то же, что и предыдущее, если оба набора используют эту форму.
  • [ЗНАК*] -- ЗНАК заполняет набор2 до длины набора1 знаками ЗНАК. Эта опция работает в конце набора2. Все символы после астерикса (*) игнорируются.
  • [ЗНАК*N] -- N копий символа ЗНАК. N подразумевается десятичным целым числом, если не начинается с 0; в этом случае считается восьмеричным целым числом.
  • [:alnum:] -- все буквы и цифры
  • [:alpha:] -- все буквы
  • [:blank:] -- все горизонтальные пробельные знаки
  • [:cntrl:] -- все управляющие знаки
  • [:digit:] -- все цифры
  • [:graph:] -- все печатные знаки, исключая пробел
  • [:lower:] -- все строчные буквы (нижний регистр)
  • [:print:] -- все печатные знаки, включая пробел
  • [:punct:] -- все знаки препинания
  • [:space:] -- все вертикальные или горизонтальные пробелы
  • [:upper:] -- все заглавные буквы (верхний регистр)
  • [:xdigit:] -- все шестнадцатеричные цифры
  • [=ЗНАК=] -- все знаки, эквивалентные ЗНАКУ

Таким образом, предыдущий пример можно записать и так:

$ echo lower_case | tr '[:lower:]' '[:upper:]' LOWER_CASE

Примечание: Должен заметить, что с изменением регистра символов кириллицы ничего не получается, по крайней мере в моей системе.

Опция -s

Это одна из самых полезных опций команды tr. Эта опция позволяет заменить повторяющиеся подряд символы из набора1 на единственный символ из списка2. Если список 2 отсутствует, то заменяет множественные символы одиночными. Чаще всего эта уплотняющая текст опция применяется для замены множественных пробелов на один единственный:

$ echo many      blank     spaces | tr -s ' '
many blank spaces

Или то же самое, используя условные обозначения:

$ echo очень     много      пробелов | tr -s \t
очень много пробелов
Вот еще один пример:

$ cat /etc/fstab | tr -s  ' ' ':'
/dev/hda5:swap:swap:defaults:0:0
/dev/hda4:/:ext3:defaults:1:1
/dev/hda1:/mnt/FreeDos:vfat:iocharset=utf8,codepage=866,
noauto,users,rw,umask=000,showexec,quiet:1:0
#/dev/hda3:/mnt/suse:ext3:iocharset=utf8,codepage=:,
noauto,users,rw,umask=000,showexec,quiet:1:0:
/dev/fd0:/mnt/floppy:vfat,msdos:iocharset=utf8,codepage=866,
noauto,users,suid,dev,exec:0:0
devpts:/dev/pts:devpts:gid=5,mode=620:0:0
proc:/proc:proc:defaults:0:0

Здесь заменили все пробелы, служащие разделителями в файле /etc/fstab, на двоеточия. Теперь можно обрабатывать этот файл другими программами, скажем cut ...тут должна быть сноска на статью о cut...

Опция -d

Используется для удаления из текста символов, перечисленных в наборе1.

$ echo a black cat | tr -d a
 blck ct

Опция может удалять также специальные символы (смотри перечень условных обозначений выше), например символ возврата каретки, который заканчивает строку в паре с символом новой строки в файлах ОС Windows. После его удаления останется только символ новой строки, который использует Юникс:

$ tr -d '\r' < ms.file < unix.file

или используя восьмеричный номер символа:

$ tr -d '\015' < ms.file > unix.file

Мне встречались утверждения, будто в некоторых реализациях команды tr возможно удалять сочетания символов (то есть слова), заключив их в кавычки:


$ echo a black cat | tr -d 'cat'
a black

Но мне такие реализации не попадались, и кавычки не влияют на результат удаления.

Опция -с

Заставляет команду работать с символами, которые отсутствуют в наборе 1. Другими словами: символы, перечисленные в наборе1 не используются в работе, а все остальные - используются. Например:

$ echo a black cat | tr -cd b-z[:cntrl:][:blank:]
blck ct
В этом примере нет буквы а, вот ее и будет удалять программа. Символы из группы [:cntrl:] нужно указать, чтобы их не удалили, иначе не происходит перенос строки, а пробел - [:blank:] - указать, чтобы он тоже остался на месте.

Или еще один изящный пример:

$ tr -cs a-zA-Z '\n' < /etc/fstab

dev
hda
swap
swap
defaults
dev
hda
ext
defaults

dev
hda
mnt
FreeDos
vfat
iocharset
utf
codepage
noauto
users
rw
umask
showexec
quiet
dev
hda
mnt
suse
ext
iocharset
utf
codepage
noauto
users
rw
umask
showexec
quiet
dev
fd
mnt
floppy
vfat
msdos
iocharset
utf
codepage
noauto
users
suid
dev
exec
devpts
dev
pts
devpts
gid
mode
proc
proc
proc
defaults
dev
sda
media
FLASHKA
vfat
rw
users
umask
showname
lower

Превращает файл /etc/fstab/ в список слов этого файла. При этом все символы, кроме букв обоих регистров, заменяются на символ переноса строки, лишние же символы переноса строки удаляет опция -s. Такого же эффекта можно достичь другим способом:

$ tr -cs "[:alpha:]" "\n" < /etc/fstab

dev
hda
swap
swap
defaults
dev
hda
ext
defaults
...

Не продолжаю из экономии места.

Резюме программы tr

Программа tr дает удивительные возможности изменять файлы, порой до неузнаваемости, простыми методами. Трудно предсказать, какое применение команде может найти пользователь, знающий ее тонкости. Особенно полезной может быть команда в качестве фильтра в составе программных каналов (pipes).

 

Hosted by uCoz