Фраза в буфере - надо транслитерировать

Обсуждение программ nnCron и nnCron LITE

Фраза в буфере - надо транслитерировать

Postby VladimirN » Fri, 17 Feb 2012, 00:05

Эту задачу выполняют многие администраторы сайтов и баз данных, обычно "руками" и медленно.

Есть строка символов на русском. Без знаков препинания. Надо с этой строкой сделать следующее.

1 Все заглавные буквы заменить маленькими-строчными.

2 Перевести строку в...э... латинский чарсет, записав латиницей. Для этого кое-кто использует разные программы и даже веб-сайт translit.cc, но хочется все сделать внутри макроса nnCron Это ведь не сложно? По-моему, надо просто набрать условия замен кирилической буквы на сочетания латинских символов.

3 В получившеся строке - все пробелы заменить дефисами.

4 Результат обратно положить в буфер обмена (CLIPBOARD)


Пример - было в буфере: Результат обратно положить в буфер обмена
стало: rezultat-obratno-polozhit-v-bufer-obmena

Я сам в деле написания макросов очень зеленый, поэтому буду благодарен за любые наброски-черновики для решения данной задачи.
VladimirN
 
Posts: 1
Joined: Thu, 16 Feb 2012, 23:52

Re: Фраза в буфере - надо транслитерировать

Postby AlikasS » Fri, 17 Feb 2012, 01:27

подключаешь в nncron.ini
плагин recode.spf
и задача тогда будет выглядеть так
Code: Select all
#( test_transliterate44
NoActive
\ WatchClipboard: "*"
: StringRep { a1 u1 a3 u3 a4 u4 \ rest a2 u2 -- } 
\ Заменить в строке a1 u1 строку a3 u3 на строку a4 u4; на стеке останется измененая строка
  1 ALLOCATE THROW TO a2
  a2 0! 0 TO u2
  a1 u1
  BEGIN OVER SWAP a3 u3 SEARCH WHILE
  TO rest SWAP 2DUP - a2 u2 2SWAP S+ TO u2 TO a2
  a4 u4 a2 u2 2SWAP S+ TO u2 TO a2
  rest u3 /STRING
  REPEAT
  a2 u2 2SWAP S+
  ROT DROP ;
CREATE trans_buf 256 ALLOT
\ Rule: TQUERY: "транслитеризация текста?" 20 No
Action:
    \ строку для перевода в промежуточный буфер
    CLIPBOARD trans_buf PLACE

\ приводим к строчным
 trans_buf COUNT LOWER-TABLE RECODE

    \ транслитерация
    trans_buf COUNT TRANSLIT-TABLE RECODE

\ меняем пробелы на - и обратно в буфер
trans_buf COUNT S"  " S" -" StringRep CLIPBOARD!

    \ показываем результат
    TMSG: "%CLIPBOARD%" 5
)#
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Фраза в буфере - надо транслитерировать

Postby Morituruz » Fri, 17 Feb 2012, 13:21

К сожалению, recode.spf это не транслит, а так.
Когда столкнулся с такой необходимостью, в икселе и блокноте настрогал своё слово.
Тут конечно аксакалы форта меня могут пристыдить за корявое решение :D , но recode.spf это совсем не вариант.
Вобщем вот так:
Code: Select all
: StringReplace { a1 u1 a2 u2  a3 u3 \ rest a4 u4 buf -- a u }  \ Заменить в строке 1 подстроку 2 на строку 3, на стеке останется измененая строка
  AT buf TO a4
  a1 u1
  BEGIN OVER SWAP a2 u2 SEARCH WHILE
    TO rest SWAP 2DUP - a4 u4 2SWAP S+ TO u4 TO a4
    a3 u3 a4 u4 2SWAP S+ TO u4 TO a4
    rest u2 /STRING
  REPEAT
  a4 u4 2SWAP S+
  ROT DROP
;
: translit
\ сначала буквосочетания:
S" ье" S" ye" StringReplace
S" ъе" S" ye" StringReplace
S" ъё" S" ye" StringReplace
S" ьё" S" ye" StringReplace

S" ае" S" aye" StringReplace
S" ее" S" eye" StringReplace
S" ёе" S" eye" StringReplace
S" ие" S" iye" StringReplace
S" йе" S" ye" StringReplace
S" ое" S" oye" StringReplace
S" уе" S" uye" StringReplace
S" ые" S" yye" StringReplace
S" эе" S" eye" StringReplace
S" юе" S" yuye" StringReplace
S" яе" S" yaye" StringReplace

S" аё" S" aye" StringReplace
S" ёё" S" eye" StringReplace
S" ёё" S" eye" StringReplace
S" иё" S" iye" StringReplace
S" йё" S" ye" StringReplace
S" оё" S" oye" StringReplace
S" уё" S" uye" StringReplace
S" ыё" S" yye" StringReplace
S" эё" S" eye" StringReplace
S" юё" S" yuye" StringReplace
S" яё" S" yaye" StringReplace

S" а" S" a" StringReplace
S" б" S" b" StringReplace
S" в" S" v" StringReplace
S" г" S" g" StringReplace
S" д" S" d" StringReplace
S" е" S" e" StringReplace
S" ё" S" e" StringReplace
S" ж" S" zh" StringReplace
S" з" S" z" StringReplace
S" и" S" i" StringReplace
S" й" S" y" StringReplace
S" к" S" k" StringReplace
S" л" S" l" StringReplace
S" м" S" m" StringReplace
S" н" S" n" StringReplace
S" о" S" o" StringReplace
S" п" S" p" StringReplace
S" р" S" r" StringReplace
S" с" S" s" StringReplace
S" т" S" t" StringReplace
S" у" S" u" StringReplace
S" ф" S" f" StringReplace
S" х" S" kh" StringReplace
S" ц" S" ts" StringReplace
S" ч" S" ch" StringReplace
S" ш" S" sh" StringReplace
S" щ" S" shch" StringReplace
S" ъ" S" " StringReplace
S" ы" S" y" StringReplace
S" ь" S" " StringReplace
S" э" S" e" StringReplace
S" ю" S" yu" StringReplace
S" я" S" ya" StringReplace
S" А" S" A" StringReplace
S" Б" S" B" StringReplace
S" В" S" V" StringReplace
S" Г" S" G" StringReplace
S" Д" S" D" StringReplace
S" Е" S" Ye" StringReplace
S" Ё" S" Ye" StringReplace
S" Ж" S" Zh" StringReplace
S" З" S" Z" StringReplace
S" И" S" I" StringReplace
S" Й" S" Y" StringReplace
S" К" S" K" StringReplace
S" Л" S" L" StringReplace
S" М" S" M" StringReplace
S" Н" S" N" StringReplace
S" О" S" O" StringReplace
S" П" S" P" StringReplace
S" Р" S" R" StringReplace
S" С" S" S" StringReplace
S" Т" S" T" StringReplace
S" У" S" U" StringReplace
S" Ф" S" F" StringReplace
S" Х" S" Kh" StringReplace
S" Ц" S" Ts" StringReplace
S" Ч" S" Ch" StringReplace
S" Ш" S" Sh" StringReplace
S" Щ" S" Shch" StringReplace
S" Ъ" S" " StringReplace
S" Ы" S" Y" StringReplace
S" Ь" S" " StringReplace
S" Э" S" E" StringReplace
S" Ю" S" Yu" StringReplace
S" Я" S" Ya" StringReplace
;


плюс слово для нижнего регистра:
Code: Select all
: LOWER-CASE   \ ( a u -- a u ) \ Перевести все символы в нижний регистр
  2DUP
  OVER + SWAP DO
    I C@
    DUP 65 91 WITHIN
      IF
        32 +  I C!
      ELSE
        DUP 192 224 WITHIN
          IF
            32 +  I C!
          ELSE
            168 =
              IF 184 I C! THEN
          THEN
      THEN
  LOOP
;


В итоге задача будет выглядеть так:
Code: Select all
#( trans-test
NoLog
NoActive
Action:
CLIPBOARD LOWER-CASE translit S"  " S" -" StringReplace CLIPBOARD!
)#


За референсный транслит я брал:
http://www.fotosav.ru/services/transliteration.aspx
Моё слово, к сожалению, не учитывает ситуации с разным регистром в начале слова и внутри, но для моих задач это и не требуется.

Конечно, правильнее бы сделать через регулярные выражения, тем более они, как оказалось, работают гораздо быстрее чем замещение строк паровозиком, но там надо хорошо подумать.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Фраза в буфере - надо транслитерировать

Postby AlikasS » Fri, 17 Feb 2012, 16:48

а чем плохо уже существующее
LOWER-TABLE RECODE
вместо
LOWER-CASE
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Фраза в буфере - надо транслитерировать

Postby Morituruz » Fri, 17 Feb 2012, 17:06

Да не хуже, просто если не пользоваться псевдотранслитом из recode.spf, то зачем вообще его подключать?
Хотя наноплюсик есть — не нужно создавать строковую переменную для буфера.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Фраза в буфере - надо транслитерировать

Postby VoidVolker » Fri, 17 Feb 2012, 17:46

Code: Select all
: CharReplace   \ ( a u char1 char2 -- a u )  \ Заменить в строке символ 1 на символ 2 и оставить строку на стеке
  2OVER OVER + SWAP DO  \ a u char1 char2
    OVER I C@ = IF DUP I C! THEN
  LOOP
  2DROP
;

Code: Select all
CREATE TranslitTable 256 CELLS ALLOT TranslitTable 256 CELLS ERASE
: gen-translit-table   \ ( -- ) \ Сгенеририровать таблицу транслиретации
  \ Таблица, один столбик, в строке - максимум до 4-х символов, если меньше - то остальные пробелы
  " y   ts  u   k   e  n   g   sh  shchz   kh  f   y   v   a   p   r   o   l   d   zh  e   ya  ch  s   m   i   t   b   yu  ye          -   "
  \ Заменяем пробелы на нули - теперь это не просто какие-то символы, а массив az-строк,
  \ Или, если говорить в терминах win-api, multi-az строка
  BL 0 CharReplace
  \ Собственно длина строки нас не интересует
  DROP
  \ А теперь раскидаем эти az-строки в таблицу транслиретации
  34 0 DO
    \ Получаем адрес очередной строки в массиве
    DUP I CELLS + DUP
    \ А теперь по индексу заменяемого символа кладем нашу строку
    Z" йцукенгшщзхфывапролджэячсмитбюёъь " I + C@ CELLS TranslitTable + 4 CMOVE
    Z" ЙЦУКЕНГШЩЗХФЫВАПРОЛДЖЭЯЧСМИТБЮЁЪЬ " I + C@ CELLS TranslitTable + 4 CMOVE
  LOOP
  \ Таблица получена, адрес массива не нужен
  DROP 
;
\ Генерируем таблицу
gen-translit-table

: my-translit   \ ( a u -- a1 u1 )
  DUP CELLS ALLOCATE THROW      \ Выделяем временный буфер для строки
  DUP 2SWAP                     \ addr0 addr0 a u \ Дублируем его и меняем местами со строкой
 
  OVER + SWAP DO    \ addr0 addr   \ Цикл по строке, на стеке текущий адрес для записи транслита
    DUP
    TranslitTable I C@ CELLS +    \ addr0 addr addr az2  \ По индексу символа получаем az-строку из таблицы для его замены
    ASCIIZ> DUP >R                \ addr0 addr addr a2 u2  R: u \ Вычисляем длину строки и сохраняем её на стеке возвратов
    ROT SWAP CMOVE                \ addr0 addr   R: u \ Записываем полученную строку по текущему адресу
    R> +                          \ addr0 addr+u    \ А длину строки прибавляем к текущему адресу
  LOOP
  OVER -                 \ Вычисляем общую длину строки - это разница между адресами первого и последнего символов
  OVER >R                   \ Сохраняем адрес стркои - это же временный буефер
  SWAP OVER S>ZALLOC SWAP   \ Выделяем новый кусок памяти для строки
  R> FREE THROW             \ Освобождаем временный буфер
;
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Фраза в буфере - надо транслитерировать

Postby Morituruz » Fri, 17 Feb 2012, 18:07

Code: Select all
" Результат обратно положить в буфер обмена" my-translit TYPE CR
gmvv-av-yevm--gda
 Ok

?
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Фраза в буфере - надо транслитерировать

Postby VoidVolker » Fri, 17 Feb 2012, 18:20

Code: Select all
" Результат обратно положить в буфер обмена" my-translit TYPE CR
ryezultat-obratno-polozhit-v-bufyer-obmyena

Ап! Исправил мелкую багу.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Фраза в буфере - надо транслитерировать

Postby Morituruz » Fri, 17 Feb 2012, 18:45

Прошу прощения, вообще-то это у меня ннкрон перешёл в кракозябры-mode.
В вашем варианте всё же не хватает буквосочетаний.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Фраза в буфере - надо транслитерировать

Postby VoidVolker » Fri, 17 Feb 2012, 18:55

Это каких это не хватает? Добавить или изменить - не проблема.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Фраза в буфере - надо транслитерировать

Postby Morituruz » Fri, 17 Feb 2012, 19:10

Например у вас буква Е всегда перекодируется в YE, а по идее это нужно только после гласных или мягкого знака, или и краткой.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Фраза в буфере - надо транслитерировать

Postby VoidVolker » Fri, 17 Feb 2012, 19:14

Так просто скопипастил с того ресурса. Такие моменты тоже можно учесть.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56


Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 4 guests

cron