Пример тупого перебора - или зачем нужна голова :)
Автор: Andy Bogdanov
Источник: https://unixdoc.ua-i.net/mirrors/unix.stat.burnet.ru/rexx/bruteforce.html
Этот простенький скриптик перебирает пары букв английская-русская, русская-английская и при нахождении подобной пары заменяет английскую букву, схожую по написанию на русскую. Т.е. - перекодировка. Сложность задачи состоит в том что в тексте имеются не только русские слова, написаные с заменой отдельных букв схожими по написанию английскими, но и примеры задач написаные полностью на английском. Естественно, заменять их русскими - нежелательно. Скрипт написан для REXX под FreeBSD (rexx-imc), но с минимальными переделками пойдет и для любой другой версии.
-------rexman.cmd-------
#!/usr/local/bin/rexx -x
s = 1
rb.1='Е'
rb.2='Т'
rb.3='У'
rb.4='О'
rb.5='Р'
rb.6='А'
rb.7='Н'
rb.8='К'
rb.9='Х'
rb.10='С'
rb.11='В'
rb.12='М'
rb.13='е'
rb.14='у'
rb.15='о'
rb.16='р'
rb.17='а'
rb.18='х'
rb.19='с'
rb.20='Л'
rb.21='Д'
rb.22='Ж'
rb.23='Э'
rb.24='Я'
rb.25='Ч'
rb.26='З'
rb.27='Ъ'
rb.28='И'
rb.29='Ц'
rb.30='Ь'
rb.31='Б'
rb.32='Ю'
rb.33='Ё'
rb.34='й'
rb.35='ц'
rb.36='Ы'
rb.37='к'
rb.38='Ф'
rb.39='н'
rb.40='г'
rb.41='ш'
rb.42='щ'
rb.43='з'
rb.44='Й'
rb.45='ъ'
rb.46='ф'
rb.47='ы'
rb.48='в'
rb.49='П'
rb.50='п'
rb.51='Г'
rb.52='Щ'
rb.53='л'
rb.54='д'
rb.55='ж'
rb.56='э'
rb.57='я'
rb.58='ч'
rb.59='Ш'
rb.60='м'
rb.61='и'
rb.62='т'
rb.63='ь'
rb.64='б'
rb.65='ю'
rb.66='ё'
ab.1='E'
ab.2='T'
ab.3='Y'
ab.4='O'
ab.5='P'
ab.6='A'
ab.7='H'
ab.8='K'
ab.9='X'
ab.10='C'
ab.11='B'
ab.12='M'
ab.13='e'
ab.14='y'
ab.15='o'
ab.16='p'
ab.17='a'
ab.18='x'
ab.19='c'
/*
тупо расписываем массивы русских и английских букв
русские - все буквы (66)
английские - только схожие по написанию (19)
*/
do s=1 to 10
/*
этот цикл на 10 повторов пришлось сделать из-за невозможности перебрать все возможные
пары букв. ведь слово может выглядеть и так - KOHCTAHTЫ
кроме буквы Ы - все остальные английские. можно было сделать сброс переменных
в циклах чтоб после нахождения одной пары и замены начинать цикл заново - но
особого выигрыша все равно не будет... проще прогнать лишний раз...
*/
aq = s+1
file='rexxman's
/*
назначаем имя входного файла
*/
do while Lines(file) \= 0
lin = LineIn(file)
if Pos('0d'x,lin) \= 0 then
if Pos('20200d'x,lin) \= 0 then lin = DelStr(lin,Pos('20200d'x,lin),3)
else lin = DelStr(lin,Pos('0d'x,lin),1)
/*
это условие удаляет символ конца строки - нужно только для юникса
*/
if Length(lin) < 2 then
do
Call LineOut 'rexxman'aq,lin
iterate
end
/*
здесь мы проверяем - а может строка пустая? зачем тогда искать там буквы :)
просто запишем эту строчку в выходной файл. для не-юникса условие будет < 3
*/
do i = 1 to 19
do m = 1 to 66
do while Pos(rb.m''ab.i,lin) \= 0
lin = Overlay(rb.m''rb.i,lin,Pos(rb.m''ab.i,lin))
/*
перебираем все возможные пары русская-английская буква и если нашли - то
перезаписываем исходную строчку, подставляя на место английской буквы соответствующую
русскую.
*/
end
do while Pos(ab.i''rb.m,lin) \= 0
lin = Overlay(rb.i''rb.m,lin,Pos(ab.i''rb.m,lin))
/*
аналогично для английская-русская...
*/
end
end
end
Call LineOut 'rexxman'aq,lin
/*
если не нашли ничего - все равно запишем в выходной файл
*/
end
end
exit
-------rexman.cmd-------
все! это конец... подумал Штирлиц. Но где же мой пистолет? :)))
у этого скрипта есть серьезный недостаток - он будет очень долго выполняться -
мне было лень думать, время было уже за 8 часов вечера, надо было идти домой и я
запустил этот скрипт на ночь...
придя утром я обнаружил что он закончился буквально за десяток минут до моего
прихода на работу :[ ] общее время обработки файла размером в 300 килобайт
на пентаре-100 составило около 11 часов :((( сначала я подумал что у меня
чем-то была занята машина - но ничего подобного! при повторном запуске все получилось
точно так же как и в первый раз... Пришлось почесать в затылке и написать новый скрипт...
-------rexman2.cmd-------
#!/usr/local/bin/rexx -x
file='rexxman'
Call Stream 'rexxman2','c','open'
do while Lines(file) \= 0
lin = LineIn(file)
if Pos('0d'x,lin) \= 0 then
if Pos('20200d'x,lin) \= 0 then lin = DelStr(lin,Pos('20200d'x,lin),3)
else lin = DelStr(lin,Pos('0d'x,lin),1)
if Length(lin) < 2 then
do
Call LineOut 'rexxman2',lin
iterate
end
do i=1 to Words(lin)
/*
делаем цикл длиной в количество слов в строке
*/
if Pos('.', translate(Word(lin,i),'$.................................................................','.'||xrange('ю','Ъ')||xrange('ё','ё')||xrange('Ё','Ё'))) > 0 then
/*
преобразуем русские буквы в слове в точки - и если они там есть то...
*/
do
word_lin = translate(Word(lin,i),'ЕТУОРАНКХСВМеуорахс','ETYOPAHKXCBMeyopaxc')
lin = Overlay(word_lin,lin,WordIndex(lin,i))
/*
преобразуем латинские буквы в слове в аналогичные русские и перезаписываем
исходную строку
*/
end
end
Call LineOut 'rexxman2',lin
/*
если ничего не нашли - то все равно записываем строчку в выходной файл
*/
end
Call Stream 'rexxman2','c','close'
exit
-------rexman2.cmd-------
вот! этот скрипт работал всего 7 минут на той же самой машине :))) еще одно его достоинство - он обрабатывает такие сочетания как т.е. - буква е является здесь английской.
Теперь нам осталось поработать немного ручками и заменить предлоги с, В, ВО ну и некоторые слова которые можно набрать полностью английскими буквами – например MECTO - но в сравнении с основной работой - это немного...