Изменение регистра букв.

Преобразование больших букв в малые.

Задача преобразования больших букв в малые решается с помощью команды s и её префиксов. Например «\U» преобразует всё дальнейшие символы в большие, а «\L» соответственно в малые. Кроме того используются префиксы «\l» и «\u», которые действуют только на первую найденную букву. Для отмены преобразования применяется префикс «\E».

Преобразовывать всё не имеет никакого практического смысла, мы будем преобразовывать только СЛОВА ЗАПИСАННЫЕ БОЛЬШИМИ БУКВАМИ. Их вообще-то сначала надо найти. Например таким ERE:

/\b[A-Z]+\b/

\b означает "граница слова", и совпадает с позицией между буквой и небуквой. Эти границы нужны для того, что-бы преобразовывались только целые СЛОВА.

Русские буквы.

В отличие от утилит вроде tr и языков вроде perl'а, sed умеет работать с русскими буквами в любой кодировке.

Замечание

Оказывается PERL всё-же умеет UTF-8, только его надо там включить особой командой.

Конечно вы должны сначала настроить свою систему на эту кодировку, и использовать либо родную sed (я думаю ваш любимый создатель дистрибутивов встроил в ваш дистрибутив правильно собранную sed), либо собирать sed самостоятельно, не забывая её правильно локализовать. Обычно на всё это не нужно обращать внимание - ваша sed скорее всего уже и так правильно работает в вашей системной кодировке. Даже если у вас японская UTF-8 («японская» в том смысле, что вы пользуетесь японским алфавитом).

Если кодировка в системе правильно настроена, то sed считает, что спецсимвол \w совпадает с любой буквой. Не только латинской, но и русской. Однако нам нужны слова не из всех букв, а только из БОЛЬШИХ. Диапазон символов не имеет смыла в данном случае, т.к. во многих кодировках русские буквы идут не подряд. Потому придётся их записывать явно:

/\b[A-ZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ]+\b/

Замечание

А когда будете записывать позаботьтесь о том, что кодировка скрипта была такой-же как в вашей системе.

Подсказка

Если вам нужно изменить текст в какой-то левой кодировке, то для начала этот документ следует перегнать в вашу кодировку вот так:

iconv -c -f cp1251 text.txt >text1.txt

ключ -c нужен для того, что-бы iconv не останавливалась на неправильных символах (которых бывает достаточно много на практике).

Впрочем можно и изменить переменные окружения так, что-бы sed заработала в какой-нибудь другой кодировке. Конечно сам скрипт тогда надо писать в той-же кодировке, что и ваш текст (а не в системной). Такой подход сложнее, но обработка текста часто происходит намного быстрее. Дело в том, что во многих системах используется кодировка UTF-8, в которой русские буквы занимают 2 байта. Что приводит к тому, что тексты на 50-100% длиннее и обрабатываются соответственно дольше (на те-же 50-100% в лучшем случае).

Использования модификатора g команды s/// с префиксами.

Вот так выглядит итоговый скрипт:

s/\b[A-ZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ]+\b/\L\u&/g

Тут использовано сразу 2 префикса: «\L» заменяет все большие буквы на малые, а «\u» меняет малые на большие. Фокус в том, что префикс «\u» - одноразовый, он сбрасывается сразу после замены первой буквы. В отличие от него, префикс «\L» никогда сам не сбрасывается. Данный скрипт срабатывает в несколько этапов:

Первым делом в строке ищутся все совпадения /RE/ и запоминаются все позиции начала и конца совпадений.

И только после полного просмотра всей строки начинаются замены. В данном случае найденное выражение меняется само на себя (используется спец-символ &). Однако во время замены все буквы меняются на малые, а первая меняется дважды - сначала на малую как и все, а потом на большую. Замена производится до конца слова, а вовсе не до конца строки. После замены первого слова начинается замена второго, и т.д..

Замечание

Данная задача впервые мне попалась на unixforum'е (бывший LinuxForum). Тамошние гуру предложили какой-то жуткий скрипт на перле, который я и не понял даже, и выяснили, что с помощью tr это невозможно. Кроме того, советовали воспользоваться vim'ом, который умеет выполнять такие команды (как и более древний ed). Конечно, в данном случае sed - самый лучший способ решения.

Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).

Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.