Отправляет email-рассылки с помощью сервиса Sendsay

KirovLUG: пользователи Linux в Вятке

За 2004-11-17

Работа над проектом Lindocs. Скрипты конверта из текущего состояния

Работа над проектом Lindocs. Скрипты конверта из текущего состояния

Создаем список обрабатываемых документов:

$ ls -1 *.html > htmllist

Удаляем те документы, которые не несут данных:

begin.html
default.html
index.html

Удалим "не-юниксовые" окончания строк в html-файлах:

$ ls -1 *.html | xargs dos2unix

Каждый файл выглядит примерно следующим образом:

<!-- тут стандартное для всех начало -->
<strong>&nbsp;&nbsp;&nbsp;&nbsp;Теоретические основы</strong><BR>
<BR>
<a href="Linux/Docs/vodol.html">В. Водолазкий "Путь к LINUX"</a><br>
<br>
<a href="Linux/other/html/acquaintance_part_01.htm">Знакомство с Linux.</a>
&nbsp;<a href="Linux/Sites/www.kuzbass.ru/docs/unixprogenv/ch1.txt">1</a>
<a href="Linux/other/html/acquaintance_part_02.htm">2</a>
<a href="Linux/other/html/acquaintance_part_23.htm">23</a><br>
В.А.Костромин. 14 дней жизни одной операционной системы.<br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="Linux/Docs/general/day_1-6.htm">День 1-6</a><br>
<a href="Linux/Sites/MyComp/224_02.htm">Висит? Снимем!</a><br>
<!-- тут стандартный для всех конец -->
Начнем писать скрипт по шагам:

Шаг первый. Вычленяем информацию из одной строки

Напишем отдeльную функцию извлекающую ссылку и ее описание из
передаваемой строки.

sub extract_data {
my($l_str) = @_[0];
my $l_link = $l_str;
my $l_desc = $l_str;
# Выделяем ссылку из строки
$l_link =~ s/(?i)(.*)\<a\shref\=\"(.*)\"\>(.*)/\2/;
# Выделяем описание из строки
$l_desc =~ s/(?i)(.*)\<a\shref\=\"(.*)\"\>(.*)\<\/a\>(.*)/\3/;
return ($l_link, $l_desc);
}
Напишем отдeльную функцию извлекающую описание темы материала,
состоящего из нескольких частей:

sub extract_topic {
my($l_str) = @_[0];
# Выделяем описание из строки
my $l_desc = $l_str;
$l_desc =~ s/(?i)^(.*)\<BR\>(.*)/\1/;
return $l_desc;
}
Напишем отдeльную функцию извлекающую описание для всего файла, т.е.
для индекса:

sub extract_index {
my($l_str) = @_[0];
my $l_desc = $l_str;
# Выделяем описание из строки
$l_desc =~ s/(?i)^\<strong\>(\&nbsp\;){4}(.*)\<\/strong\>(.*)/\2/;
return $l_desc;
}
Шаг второй. Определение типа строки

Необходимо определять вид(тип) строки, для того чтобы определять
какую информацию из нее нужно извлекать и какой xml-блок генерировать
после. Напишем функцию, которая определяла бы тип строки, выбирая
эту строку по номеру из глобального массива всех строк, входящих в файл.

sub def_str_type {
my ($l_num) = @_[0];
my $l_res = 0;
# Строка, которая выглядит как обычная
if ( @f_array[$l_num] =~ /(?i)^\<a\shref.*\<br\>/ ) {
# Надо проверить следующие за ней
if ( def_str_type($l_num+1) == 31 ) {
# Строка - начало материала из нескольких частей с одной темой
# так как за ней соответствующая строка
$l_res = 30;
}
else {
# Все таки обычная строка
$l_res = 1;
}
}
# Строка - начало материала из нескольких частей
elsif ( @f_array[$l_num] =~ /(?i)^\<a\shref/ ) {
$l_res = 2;
}
# Строка - продолжение и конец материала из нескольких частей
elsif ( @f_array[$l_num] =~ /(?i)^\s+.*\<a\shref/ ) {
$l_res = 21;
}
# Строка - продолжение и конец материала из нескольких частей с одной
темой
elsif ( @f_array[$l_num] =~ /(?i)^(\&nbsp\;){2,}.*\<a\shref.*\<br\>/
) {
$l_res = 31;
}
# Строка выглядит как не несущая в себе данных, но за ней продолжение
материала
# состоящего из нескольких частей, значит, данная строка начало этого
материала
elsif ( ( $l_num+1 < $#f_array ) && ( def_str_type($l_num+1) == 31 )
) {
$l_res = 3;
}
return $l_res;
}
Видно, что внутри функции происходит ее рекурсивный вызов...

Шаг третий. Генерация xml-блоков

Процедура, которая учитывает переданные ей параметры и в зависимости
от них генерирует xml-блок для ссылки:

sub generate_record {
my ($l_type, $l_id, $l_part, $l_link, $l_desc, $l_index) = @_;
# Генерируем xml-блок
my $l_res = "";
$l_res = $l_res." <element";
length($l_type) != 0 ? $l_res = $l_res." type=\"topic\"" : $l_res = $l_res;
length($l_id) != 0 ? $l_res = $l_res." id=\"".$l_id."\"" : $l_res = $l_res;
length($l_part) != 0 ? $l_res = $l_res." part=\"".$l_part."\"" : $l_res
= $l_res;
$l_res = $l_res.">\n";
length($l_link) != 0 ? $l_res = $l_res." <link type=\"rel\">".$l_link."</link>\n"
: $l_res = $l_res;
$l_res = $l_res." <desc>".$l_desc."</desc>\n";
$l_res = $l_res." <author></author>\n";
$l_res = $l_res." <index>".$l_index."</index>\n";
$l_res = $l_res." </element>\n";
return $l_res;
}
Процедура, которая учитывает переданные ей параметры и в зависимости
от них генерирует xml-блок для индекса:

sub generate_index {
my ($l_index, $l_desc) = @_;
# Генерируем xml-блок
my $l_res = "";
$l_res = $l_res." <index>\n";
$l_res = $l_res." <value>".$l_index."</value>\n";
$l_res = $l_res." <parent></parent>\n";
$l_res = $l_res." <desc>".$l_desc."</desc>\n";
$l_res = $l_res." </index>\n";
return $l_res;
}
Шаг четвертый. Работа с содержимым html-файла

Итак, нужно последовательно перебирать все строки файла,
определять их тип, извлекать из нее нужные данные и генерировать
xml-блоки. Так как при генерации блока для ссылок, обозначающих
материал состоящий из нескольких частей, необходим уникальный
идентификатор, то его генерировать будем с помощью функции md5_base64
из модуля Digest::MD5.

while ( $count < $#f_array ) {
# Выбираем строки по одной
$next_s = @f_array[$count];
# Подошли к концу файла
if ( $is_content && ( ( $cur_s =~ /(?i)^\<\/BODY/ ) && ( $next_s =~ /(?i)^\<\/HTML/
) ) ) {
$is_content = 0;
}
if ( $is_content ) {
# В зависимости от типа строки генерируем необходимый элемент
$str_type = def_str_type($count-1);
if ( $str_type == 1 ) {
$xml_block = $xml_block.generate_record("", "", "", extract_data($cur_s),
$cur_index);
}
elsif ( $str_type == 2 ) {
$id_in = md5_base64($cur_s);
$part_in = 0;
$xml_block = $xml_block.generate_record("", $id_in, $part_in,
extract_data($cur_s), $cur_index);
}
elsif ( $str_type == 21 ) {
$part_in += 1;
$xml_block = $xml_block.generate_record("", $id_in, $part_in,
extract_data($cur_s), $cur_index);
}
elsif ( $str_type == 3 ) {
$id_in = md5_base64($cur_s);
$xml_block = $xml_block.generate_record(1, $id_in, "", "", extract_topic($cur_s),
$cur_index);
}
elsif ( $str_type == 30 ) {
$id_in = md5_base64($cur_s);
($var, $topic) = extract_data($cur_s);
$xml_block = $xml_block.generate_record(1, $id_in, "", "", $topic,
$cur_index);
$xml_block = $xml_block.generate_record("", $id_in, "", extract_data($cur_s),
$cur_index);
}
elsif ( $str_type == 31 ) {
$xml_block = $xml_block.generate_record("", $id_in, "", extract_data($cur_s),
$cur_index);
}
else {
print $cur_s."\n";
}
}
# Сейчас начнутся ссылки на материал
if ( ! $is_content && ( ( $cur_s =~ /(?i)^\<BR/ ) && ( $prev_s =~ /(?i)^\<strong/
) ) ) {
$is_content = 1;
$index_block = generate_index($cur_index, extract_index($prev_s));
}
$prev_s = $cur_s;
$cur_s = $next_s;
$count += 1;
}
Шаг пятый - заключительный. Сварка и спайка

После сварки и спайки получился следующий скрипт:

begin genrate.pl #!/usr/bin/perl

# Импортируем функцию из модуля, необходимую для генерации уникальных
# идентификаторов
use Digest::MD5 qw(md5_base64);

# Считываем параметры переданные из командной строки
# Имя файла с листингом обрабатываемых файлов
my $f_list = @ARGV[0];
# Имя файла куда помещаются результаты
my $f_out = @ARGV[1];

# Начальные значения рабочих переменных
# xml-блок, где накапливаются индексы
my $xml_index = " <indexes>\n";
# xml-блок, где накапливаются ссылки
my $xml_content = " <content>\n";
# Переменные, в которых находятся текущий индексный блок и текущий блок
# ссылок
my $t_xi = "";
my $t_xc = "";

##
# Функция: convert_one
# Входные параметры: $f_name: строковая величина
# Выходные данные: $index_block: строковая величина
# $xml_block: строковая величина
# Описание: Выполняет преобразование из html-файла, имя
# которого передано во входном параметре, в xml-блок по определенным
# правилам. В итоге получается два xml-блока: для индексной секции и
# секции ссылок. Эти блоки возвращаются как результат функции
sub convert_one {
# Имя файла, с которым работаем
my ($f_name) = $_[0];
# Список строк, входящих в файл
local @f_array = ();
# Заполняем список строк
open(F_IN, $f_name) || die "cannot open $f_name for reading: $!";
while (<F_IN>) {
chomp;
push(@f_array, $_);
}
# Закрываем файл
close(F_IN) || die "can't close $f_name: $!";
# Текущий индекс для документа
my $cur_index = substr($f_name, 0, length($f_name)-5);
# Начальное значение, обрабатываемой строки
my $cur_s = "";
# Строки вокруг обрабатываемой
my $prev_s = "";
my $next_s = "";
# Флаг наличия содержания
my $is_content = 0;
# Первоначальное значение счетчика строк
my $count = 0;
# Переменные, куда будет помещаться xml-блок, возращаемый как
# результат
my $index_block = "";
my $xml_block = "";

##
# Функция: generate_record
# Входные параметры: $l_type: строковая величина
# $l_id: строковая величина
# $l_part: строковая величина
# $l_link: строковая величина
# $l_desc: строковая величина
# $l_index: строковая величина
# Выходные данные: $l_res: строковая величина
# Описание: Генерирует xml-запись, атрибутами и полями которой
# являются переданные функции параметры. Сгенерированная запись
# помещается в переменную, которую функция возвращает как результат
sub generate_record {
my ($l_type, $l_id, $l_part, $l_link, $l_desc, $l_index) = @_;
# Генерируем xml-блок
my $l_res = "";
$l_res = $l_res." <element";
length($l_type) != 0 ? $l_res = $l_res." type=\"topic\"" : $l_res
= $l_res;
length($l_id) != 0 ? $l_res = $l_res." id=\"".$l_id."\"" : $l_res
= $l_res;
length($l_part) != 0 ? $l_res = $l_res." part=\"".$l_part."\"" :
$l_res = $l_res;
$l_res = $l_res.">\n";
length($l_link) != 0 ? $l_res = $l_res." <link type=\"rel\">".$l_link."</link>\n"
: $l_res = $l_res;
$l_res = $l_res." <desc>".$l_desc."</desc>\n";
$l_res = $l_res." <author></author>\n";
$l_res = $l_res." <index>".$l_index."</index>\n";
$l_res = $l_res." </element>\n";
return $l_res;
}

##
# Функция: generate_index
# Входные параметры: $l_index: строковая величина
# $l_desc: строковая величина
# Выходные данные: $l_res: строковая величина
# Описание: Генерирует xml-запись, атрибутами и полями которой
# являются переданные функции параметры. Сгенерированная запись
# помещается в переменную, которую функция возвращает как результат
sub generate_index {
my ($l_index, $l_desc) = @_;
# Генерируем xml-блок
my $l_res = "";
$l_res = $l_res." <index>\n";
$l_res = $l_res." <value>".$l_index."</value>\n";
$l_res = $l_res." <parent></parent>\n";
$l_res = $l_res." <desc>".$l_desc."</desc>\n";
$l_res = $l_res." </index>\n";
return $l_res;
}

##
# Функция: extract_data
# Входные параметры: $l_str: строковая величина
# Выходные данные: $l_link: строковая величина
# $l_desc: строковая величина
# Описание: Извлекает из входной строки ссылку и описание
# материала, которые потом возвращает как результат
sub extract_data {
my($l_str) = @_[0];
my $l_link = $l_str;
my $l_desc = $l_str;
# Выделяем ссылку из строки
$l_link =~ s/(?i)(.*)\<a\shref\=\"(.*)\"\>(.*)/\2/;
# Выделяем описание из строки
$l_desc =~ s/(?i)(.*)\<a\shref\=\"(.*)\"\>(.*)\<\/a\>(.*)/\3/;
return ($l_link, $l_desc);
}

##
# Функция: extract_topic
# Входные параметры: $l_str: строковая величина
# Выходные данные: $l_desc: строковая величина
# Описание: Извлекает из входной строки описание материала,
# которое является описанием для целой темы
sub extract_topic {
my($l_str) = @_[0];
# Выделяем описание из строки
my $l_desc = $l_str;
$l_desc =~ s/(?i)^(.*)\<BR\>(.*)/\1/;
return $l_desc;
}

##
# Функция: extract_index
# Входные параметры: $l_str: строковая величина
# Выходные данные: $l_desc: строковая величина
# Описание: Извлекает из входной строки описание, которое
# является описанием индекса
sub extract_index {
my($l_str) = @_[0];
my $l_desc = $l_str;
# Выделяем описание из строки
$l_desc =~ s/(?i)^\<strong\>(\&nbsp\;){4}(.*)\<\/strong\>(.*)/\2/;
return $l_desc;
}

##
# Функция: def_str_type
# Входные параметры: $l_num: целое число
# Выходные данные: $l_res: строковая величина
# Описание: Функция работает с глобальным массивом @f_array,
# определяя тип строк, которые в него входят, номер строки - $l_num
# Тип, определенный у строки, возращается как результат. В функции
# происходит рекурсивный вызов самой себя.
# Возвращаемые типы:
# 0 - строка не несущая информации
# 1 - обычная ссылка
# 2 - ссылка - начало материала из нескольких частей
# 21 - ссылка - продолжение или конец материала из нескольких частей
# 3 - строка - начало материала из нескольких частей с одной темой
# 30 - ссылка - начало материала из нескольких частей с одной темой
# 31 - ссылка - продолжение или конец материала из нескольких частей
# с одной темой
sub def_str_type {
my ($l_num) = @_[0];
my $l_res = 0;
# Строка, которая выглядит как обычная
if ( @f_array[$l_num] =~ /(?i)^\<a\shref.*\<br\>/ ) {
# Надо проверить следующие за ней
if ( def_str_type($l_num+1) == 31 ) {
# Строка - начало материала из нескольких частей с одной
темой
# так как за ней соответствующая строка
$l_res = 30;
}
else {
# Все таки обычная строка
$l_res = 1;
}
}
# Строка - начало материала из нескольких частей
elsif ( @f_array[$l_num] =~ /(?i)^\<a\shref/ ) {
$l_res = 2;
}
# Строка - продолжение и конец материала из нескольких частей
elsif ( @f_array[$l_num] =~ /(?i)^\s+.*\<a\shref/ ) {
$l_res = 21;
}
# Строка - продолжение и конец материала из нескольких частей с одной
темой
elsif ( @f_array[$l_num] =~ /(?i)^(\&nbsp\;){2,}.*\<a\shref.*\<br\>/
) {
$l_res = 31;
}
# Строка выглядит как не несущая в себе данных, но за ней продолжение
материала
# состоящего из нескольких частей, значит, данная строка начало этого
материала
elsif ( ( $l_num+1 < $#f_array ) && ( def_str_type($l_num+1) == 31
) ) {
$l_res = 3;
}
return $l_res;
}

# Цикл выборки строк из файла
while ( $count < $#f_array ) {
# Выбираем строки по одной
$next_s = @f_array[$count];
# Подошли к концу файла
if ( $is_content && ( ( $cur_s =~ /(?i)^\<\/BODY/ ) && ( $next_s
=~ /(?i)^\<\/HTML/ ) ) ) {
$is_content = 0;
}
if ( $is_content ) {
# В зависимости от типа строки генерируем необходимый элемент
$str_type = def_str_type($count-1);
if ( $str_type == 1 ) {
$xml_block = $xml_block.generate_record("", "", "", extract_data($cur_s),
$cur_index);
}
elsif ( $str_type == 2 ) {
$id_in = md5_base64($cur_s);
$part_in = 0;
$xml_block = $xml_block.generate_record("", $id_in, $part_in,
extract_data($cur_s), $cur_index);
}
elsif ( $str_type == 21 ) {
$part_in += 1;
$xml_block = $xml_block.generate_record("", $id_in, $part_in,
extract_data($cur_s), $cur_index);
}
elsif ( $str_type == 3 ) {
$id_in = md5_base64($cur_s);
$xml_block = $xml_block.generate_record(1, $id_in, "", "",
extract_topic($cur_s), $cur_index);
}
elsif ( $str_type == 30 ) {
$id_in = md5_base64($cur_s);
($var, $topic) = extract_data($cur_s);
$xml_block = $xml_block.generate_record(1, $id_in, "", "",
$topic, $cur_index);
$xml_block = $xml_block.generate_record("", $id_in, "", extract_data($cur_s),
$cur_index);
}
elsif ( $str_type == 31 ) {
$xml_block = $xml_block.generate_record("", $id_in, "", extract_data($cur_s),
$cur_index);
}
else {
print $cur_s."\n";
}
}
# Сейчас начнутся ссылки на материал
if ( ! $is_content && ( ( $cur_s =~ /(?i)^\<BR/ ) && ( $prev_s =~
/(?i)^\<strong/ ) ) ) {
$is_content = 1;
$index_block = generate_index($cur_index, extract_index($prev_s));
}
$prev_s = $cur_s;
$cur_s = $next_s;
$count += 1;
}
return ($index_block, $xml_block);
}

# Выбираем по одной строки из файла со списком - определяем имя
# обрабатываемого файла.
open(F_LIST, $f_list) || die "cannot open $f_list for reading: $!";
while (<F_LIST>) {
chomp;
# Вызыаем процедуру конверта для данного файла
($t_xi, $t_xc) = convert_one($_);
# Накапливаем полученные результаты
$xml_index = $xml_index.$t_xi;
$xml_content = $xml_content.$t_xc;
}
close(F_LIST) || die "can't close $f_list: $!";
# Ставим закрывающие теги в блоках
$xml_index = $xml_index." </indexes>\n";
$xml_content = $xml_content." </content>\n";
# Формируем выходной файл
open(F_OUT,">".$f_out) || die "cannot open $f_out for write: $!";
print F_OUT "<lindocs>\n";
print F_OUT $xml_index;
print F_OUT $xml_content;
print F_OUT "</lindocs>\n";
close(F_OUT) || die "can't close $f_out: $!";
end genrate.pl В качестве входноых параметров для него передается имя файла со
списком обрабатываемых файлов и выходной файл, в который будет помещено
получившееся xml-дерево.

   2004-11-17 18:06:39 (#266277)

linuxовка

Очередное сборище linuxового народа состоится на Театральной площади у
сцены в ПЯТНИЦУ (19 ноября) в 18.00. Приглашаются все желающие.

Кто может опоздать - предупредите заранее - на сколько, чтобы мы вас
подождали.

   2004-11-17 14:51:24 (#266144)

Re: ir

> Поинтересуйся у них, только сразу не говори им, что ты линуксовод и
> слэнга и терминов побольше, они от этого в кататонический ступор впадают
> - получишь большое удовольствие. ;)

:)

> http://www.nixp.ru/cgi-bin/go.pl?q=articles;a=linux_gprs
> Посмотри еще на linuxcenter, там пара статей есть.

ок, спасибо

> > в линухе придется изворачиваться (то есть
> > если мне нужно срочно, то этой ОС доверять я НЕ МОГУ).
> А если б к твоему девайсу виндовых дровов не было, или, того хуже, они
> кривые, что бы ты делал? Вероятно, одно из трех:

в основном я встречался с проблемой, что устройство не поддерживается
следующей версией винды и дров нет...

сейчас вот хочу найти аналог fractal explorer для линукс (уже нашел пару
программ, которые, на первый взгляд, чуть поуже в функциональности,
разбираюсь с ними). Уж больно красиво получается. Кто-нибудь таким
занимался? У меня вторая (кроме рабочей) машина на линукс, я ее бы на
круглосуточный рендеринг бы поставил для анимации.

-*Информационный канал Subscribe.Ru
Подписан адрес:
Код этой рассылки: comp.soft.linux.kirovlug
Написать в лист: mailto:comp.soft.linux.kirovlug-list@subscribe.ru
Отписаться: mailto:comp.soft.linux.kirovlug--unsub@subscribe.ru?subject=comp.soft.linux.kirovlug

http://subscribe.ru/ http://subscribe.ru/feedback

   2004-11-17 00:45:47 (#265793)

Re: ir

> как находится по "принять irda windows"... Ладно, это уже мои проблемы:
> извините за беспокойство. Буду искать..

А ты в справочной службе своего сотового оператора не спрашивал? :)
Поинтересуйся у них, только сразу не говори им, что ты линуксовод и
слэнга и терминов побольше, они от этого в кататонический ступор впадают
- получишь большое удовольствие. ;)

http://www.nixp.ru/cgi-bin/go.pl?q=articles;a=linux_gprs
Посмотри еще на linuxcenter, там пара статей есть.

> в линухе придется изворачиваться (то есть
> если мне нужно срочно, то этой ОС доверять я НЕ МОГУ).

А если б к твоему девайсу виндовых дровов не было, или, того хуже, они
кривые, что бы ты делал? Вероятно, одно из трех:
1. Кучеряво крыл бы матом дядю Билли и его винды; либо
2. Терпеливо ждал выхода самой распоследней версии своих кривых дровов с
цифровой подписью и тестом на совместимость; либо
3. Заглянул в комикс, именуемый "справкой", НО это от отчаяния, т.к. ты
и так знаешь, что ничего путного там нет.
Но, скорее всего, все вместе, и не по разу.

> Вот почему в виндовс все так просто: у меня есть телефон и комовский
> ик-порт, и я заранее знаю, что мне не нужно будет никакого софта и
> никаких даже дров

Вот поэтому винды и весят как DVD, и память жрут, как гангрена
конечности - все-то там есть и все установлено, но большей частью то, о
чем ты даже не слышал и что тебе ни в жисть не понадобится. И именно
поэтому нужно как следует попотеть, чтобы из продукта сделать подобие
операционки. А в Линухе (более-менее приличном дистрибутиве) тоже все
есть, только нужно это установить, и, возможно, пару файлов поправить -
делов-то. А как править - на это подробнейшая дока есть. Я предпочитаю
знать, ЧТО и КУДА ставлю, и КАК это работает.

Кстати, когда я жпрез у себя ставил, я тоже думал, что не смогу в Линухе
его настроить, поэтому начал с виндов. Провозился ночь, винды погибли в
неравной борьбе с юэсбами. В Линухе настройка заняла от силы десять
минут, причем большая часть времени ушла на поиск документации.

   2004-11-17 00:09:00 (#265778)