|
В своем посте Транслитерация системных имен по ГОСТ 7.79—2000 я коснулся вопроса транслитерации русских имен в латинский алфавит и пообещал написать скрипт, который будет выполнять такую операцию.
Для создания скрипта потребовалось более глубокое изучение вопроса. И обнаружились некоторые подводные камни.
Во-первых, нужно было найти оригинальную таблицу транслитерации из ГОСТ-а. Оказалось, что в Интернете масса вариантов таблицы транслитерации, при чем утверждалось, что это именно таблица из ГОСТ 7.79-2000. Но все они было разные!!! Я понял, что это только начало кошмара и не ошибся.
Наконец мне удалось найти оригинал ГОСТ-а на официальном сайте «Федерального агентства по техническому регулированию и метрологии» http://protect.gost.ru (именно эта организация ныне заведует ГОСТ-ми). Сайт очень странный: поиск не работает, документов мало – и это официальный сайт!!! Кошмар! Как чиновникам удается извратить достижения прогресса в виде Интернета!? Тем не менее, отсканированная версия ГОСТ 7.79—2000 там есть. Только вот качество ужасное. Поэтому пришлось взять таблицу с одного из сайтов в Интернете и поправить ее в соответствии с ГОСТ. В конце концов, мне удалось найти pdf-ку с отсканированным ГОСТ-ом хорошего качества (не знаю насколько это законно, поэтому ссылку не привожу) и выправить таблицу транслитерации.
После этого был использован Excel и PowerShell для превращения таблицы в ассоциативный массив PowerShell – это стало основой скрипта транслитерации. Использование ассоциативного массива позволяет отказаться от операторов «–creplace» и выполнять замену букв за один проход исходной строки: скрипт получается более красивым, более читабельным и более эффективным.
Второй подводный камень обнаружился в самом PowerShell, В нем все операции сравнения строк (символов) являются «case insensitive», т.е. независимыми от регистра. Оказывается это работает и для ключей ассоциативного массива. Это означает, что конструкция:
$T = @{
"а"="a"
"А"="T"
"б"="b"
"в"="v"
}
как и конструкция:
$T = @{
'а'="a"
'А'="T"
'б'="b"
'в'="v"
}
вызывает ошибку «Duplicate keys 'А' are not permitted in hash literals.»
Прикольно! Вот так грабли в чистом поле! Как же быть? Пришлось переделать конструкцию инициализации ассоциативного массива:
$T = @{
[char]'а'="a"
[char]'А'="T"
[char]'б'="b"
[char]'в'="v"
}
Как теперь с этим работать? Вызов $T['А'] возвращает «пусто»!!! Попробуем так $T[[char]'А'] – вернул «T». Сработало! Значит, PowerShell всегда преобразует тип Char к String да еще игнорирует регистр - это удобно в большинстве случаев, но в случае с ассоциативными массивами это, как видно, приводит к ошибкам. Как же сделать ассоциативный массив с «case insensitive» ключами? (Кстати в Perl можно задать режим, когда подобным местах неявных преобразований типов среда исполнения выдает предупреждение, в VBScript можно задать «Option Strict On», а вот как же PowerShell???)
Если теперь исходную строку преобразовать в массив символов:
$inChars = $inString.ToCharArray()
и организовать перебор всех символов:
foreach ($c in $inChars)
то можно использовать обращение к таблице транслитерации в виде:
$Table[$c]
или
$Table.$c
Ну и напоследок обнаружился еще один подводный камень. В гостовской таблице для некоторых букв использовали непонятные знаки. Речь о буквах «Ъ» - «”», «Ы» - «Y’», «Ь» - «’», «Э» - «E’». Что это за штрихи такие?
Пришлось обратиться к еще одному документу ГОСТ 7.28-2002 (ИСО 5426-83, ИСО 5426-2-96) «Расширенный набор символов латинского алфавита для обмена информацией». Согласно этому ГОСТ-у для обозначения символов «мягкий знак» и «твердый знак» используются специальные символы обозначенные в ГОСТ-е как 3/13 и 3/14!!! Но как их вводить с клавиатуры?! Естественно никак. Значит, мы обречены на использование обычных кавычек – двойной и одинарной? Но эти символы не допустимы в системных именах – смотрите KB909264 «Naming conventions in Active Directory for computers, domains, sites, and OUs».
Еще вариант: использовать символ «`» Называется «Гравис» («Grave») или «Слабое ударение» Этот символ пригоден (!!!) для использования в системных именах. Не верите? Смотрите официальную статью, приведенную выше, или попробуйте сами.
Но! Я просто не решился использовать этот символ в системных именах компьютеров и пользователей. Поэтому в скрипте сделана такая замена: для мягкого и твердого знаков использован знак минус, а для букв «Ы» и «Э» оставлен один латинский символ:
[char]'ъ' = "-" # "``" оригинал(?)
[char]'Ъ' = "-" # "``"
[char]'ы' = "y" # "y`"
[char]'Ы' = "Y" # "Y`"
[char]'ь' = "-" # "`"
[char]'Ь' = "-" # "`"
[char]'э' = "e" # "e`"
[char]'Э' = "E" # "E`"
И это тема для дискуссии: поставить «Гравис» или заменить «`» на знак минуса «-»? А может заменить на пустой символ «», т.е. вообще игнорировать?
Твердый знак в именах вроде бы вообще не используется. Буква «Э» очень и очень редко. Буква «Ы» очень редко. Буква «Ь» редко. Это означает, что проблема касается узкого круга имен. Но, тем не менее, проблема есть.
Остается сказать, что скрипт прилагается.
Удачи в присвоении имен!
Читать далее
Категория:
Scripts, Транслитерация
Attachment(s): Translit-ToLAT.zip
|