Глава 15: Другие операции преобразования данных.
15.5 Транслитерация
Если вам необходимо взять строку и заменить все зкземпляры какого-нибудь символа другим символом или удалить их, это можно сделать, как вы уже знаете, с помощью тщательно подобранных команд s///. Предположим, однако, вам нужно превратить все буквы а в буквы b, а все буквы b — в буквы а. Это нельзя сделать посредством двух команд s///, потому что вторая команда отменит все изменения, сделанные первой.
Такое преобразование данных очень просто выполняется в shell с помощью стандартной команды tr(l):
tr ab ba <indata >outdata
(Если вы ничего не знаете о команде tr, загляните на man-страницу tr(l); это полезный инструмент.) В Perl тоже применяется операция tr, которая работает в основном так же:
tr/ab/ba;
Операция tr принимает два аргумента: старая_строка и новая_строка. Они используются так же, как аргументы команды s///; другими словами, имеется некий разделитель, который стоит сразу же за ключевым словом tr и разделяет и завершает аргументы (в данном случае это косая черта, но в этой роли могут виступать почти все символы).
Аргументи операции tr похожи на аргументи команды tr(l). Операция tr изменяет содержимое переменной $_ (совсем как si/I}, отыскивая в ней символы старой строки и заменяя найденные символы соответствующими символами новой строки. Вот несколько примеров:
$_ = "fred and barney";
tr/fb/bf; # $ теперь содержит "bred and farney"
tr/abcde/ABCDE/; # $_ теперь содержит "BrED AnD fArnEy"
tr/a-z/A-Z/; # $_ теперь содержит "BRED AND FARNEY"
Обратите внимание на то, что диапазон символов можно обозначить двумя символами, разделенными дефисом. Если вам нужен в строке дефис как таковой, поставьте перед ним обратную косую.
Если новая строка короче старой, то последний символ новой строки повторяется столько раз, сколько нужно для того, чтобы строки имели одинаковую длину, например:
$_ = "fred and barney";
tr/a-z/x/; # $_ теперь содержит "хххх xxx xxxxxx"
Чтобы такое не происходило, поставьте в конце операции tr/// букву d, которая означает delete ("удалить"). В данном случае последний символ не повторяется. Все символы старой строки, для которых нет соответствующих символов в новой строке, просто удаляются:
$ = "fred and barney";
tr/a-z/ABCDE/d; # $_ теперь содержит "ED AD BAE"
Обратите внимание на то, что все буквы, стоящие после буквы е, исчезают, потому что в новом списке соответствующей буквы нет, и на то, что на пробелы это не влияет, потому что их нет в старом списке. По принципу работы это зквивалентно команде tr c опцией -d.
Если новый список пуст и опция d не используется, то новый список будет совпадать со старым. Это может показаться глупым — зачем заменять І на І и 2 на 2? — но на самом деле в этом есть довольно глубокий смысл. Операция tr/// возвращает количество символов, совпавших со старой строкой, и путем замены символов на самих себя вы можете получить число таких символов, содержащихся в новой строке*. Например:
* Это справедливо только для одиночних символов. Для подсчета строк в операции сопоставления с образцом используйте флаг /д:
while (/образец/д) {
$count++;
}
$_ = "fred and barney";
$count = tr/a-z//; # $_ не изменилась, но $count = 13
$count2 = tr/a-z/A-Z/; # $_ переведена в верхний регистр, и $count2 = 13
Если в конце операции добавить букву с (как мы добавляли букву d), символы старой строки будут рассматриваться как исключение из набора всех 256 символов. Каждый символ, указаними в старой строке, удаляется из совокупности всех возможных символов; оставшиеся символы, взятые по порядку от младшего к старшему, образуют новую строку-результат. Например, подсчитать или изменить в нашей строке все символы, не являющиеся буквами, можно так:
$_ = "fred and barney";
$count = tr/a-z//c; # $_ не изменилась, но $count = 2
tr/a-z/_/c;
# $_ теперь содержит "fred_and_barney" (символы-небуквы => _)
tr/a-z//cd;
# $_ теперь содержит "fredandbarney" (символы-небуквы удалены)
Отметим, что эти опции можно обьединять, как показано в последнем примере, где мы сначала меняем совокупность символов на "дополняющую" (список букв становится списком всех символов-небукв), а затем с помощью опции d удаляем все символы этой совокупности.
Последняя опция операции tr/// —s, которая заменяет множество зкземпляров одной преобразованной буквы одним. Например:
$_ = "aaabbbcccdefghi";
tr/defghi/abcddd/s; # $_ теперь содержит "aaabbbcccabcd"
Обратите внимание: буквы def заменены на abc, a ghi (которые без опции s превратились бы в ddd) стали одной буквой d. Отметим также, что стоящие друг за другом буквы в первой части строки "не сжимаются", потому что для них не задано преобразование. Вот еще несколько примеров:
$_ = "fred and barney, wilma and betty";
tr/a-z/X/s; ” $_ теперь содержит "X X X, X X X"
$_ = "fred and barney, wilma and betty";
tr/a-z/_/cs; # $_ теперь содержит "fred_and_barney_wilma and betty"
В первом из этих примеров каждое слово (стоящие друг за другом буквы) было заменено одной буквой х. Во втором примере все группы стоящихдруг за другом символов-небукв стали одиночними знаками подчеркивания.
Как и команда s///, операция tr может быть проведена над другой строкой, а не только над строкой, хранящейся в переменной $_. Это достигается с помощью операции =~:
$names = "fred and barney";
$names =~ tr/aeiou/X/; # $names теперь содержит "frXd Xnd bXrnXy"
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|