Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Парсинг html. Посчитать количество вхождений


Автор: ochkasty 16.2.2011, 15:02
Нужно посчитать сколько раз в html-файле встречается эта комбинация:

((^\<tr\sclass\=ltr\>$^\<td\>)|(^\<tr\>$^\<td\>)|(^\<tr\>$^\<td\sclass\=port\>))B\#

(Данный набор использовал в плагине "Search and Replace" для FAR manager, поэтому сильно не пинайте, если где-то ошибся).

Умею только читать файл целиком: 

Код

open (F, 'xcn_156.htm'); 
while(read(F, $tmp, 1)!=0){; 
$str.=$tmp; 
} 


После этого, в переменной $str получаю полное содержимое файла xcn_156.htm. Что с ним потом делать?

Спасибо.

Автор: Grost 16.2.2011, 16:47
А почему бы сразу во время считывания данных не поставить счётчик с условием?
PS. хотя может не совсем понял, что требуетсяsmile

Автор: arto 16.2.2011, 17:26
$cnt = () = $str =~ m#\Q((^\<tr\sclass\=ltr\>$^\<td\>)|(^\<tr\>$^\<td\>)|(^\<tr\>$^\<td\sclass\=port\>))B\\\#\E#g

Автор: ochkasty 17.2.2011, 10:04
Цитата(Grost @ 16.2.2011,  16:47)
А почему бы сразу во время считывания данных не поставить счётчик с условием?
PS. хотя может не совсем понял, что требуетсяsmile

Да, можно сразу во время считывания. Как? Подскажи, пожалуйста.

Автор: Grost 17.2.2011, 10:41
возможно так, если считывать построчно:
Код

while(<F>)
{if(m#\Q((^\<tr\sclass\=ltr\>$^\<td\>)|(^\<tr\>$^\<td\>)|(^\<tr\>$^\<td\sclass\=port\>))B\\\#\E){$i++;}
}


либо сначала разбить на строки потом обрабатывать:
Код

@str=split('\n', $str);
while(<@str>)
{if(m#\Q((^\<tr\sclass\=ltr\>$^\<td\>)|(^\<tr\>$^\<td\>)|(^\<tr\>$^\<td\sclass\=port\>))B\\\#\E){$i++;}
}

Только я регулярку может не правильно переписал smile
А вообще у arto, вариант лучше будет. 

Автор: ochkasty 17.2.2011, 14:55
Цитата(arto @ 16.2.2011,  17:26)
$cnt = () = $str =~ m#\Q((^\<tr\sclass\=ltr\>$^\<td\>)|(^\<tr\>$^\<td\>)|(^\<tr\>$^\<td\sclass\=port\>))B\\\#\E#g

Да, этот вариант вполне удобен. Спасибо. 

Однако, здесь, почему-то, не ищется символ начала строки:

$cnt = () = $str =~ m/^\<tr/g; -- говорит, что таких вхождений нет. Хотя точно есть. Я смотрел по F4.

Почему?

Автор: alezzz 17.2.2011, 15:02
$cnt = () = $str =~ m/^\<tr/gm

Автор: arto 17.2.2011, 15:53
потому как \Q

либо напишите правильный regexp, либо расскажите руками, что вам надо найти.

Автор: ochkasty 17.2.2011, 16:33
Цитата(arto @ 17.2.2011,  15:53)
потому как \Q

либо напишите правильный regexp, либо расскажите руками, что вам надо найти.

Мне нужно посчитать количество таких вхождений:

- первая строка: пустая
- вторая строка полностью: <tr class=ltr> или <tr>
- третья строка начинается с: <td>B# или <td class=port>B#

Код

[пустая строка]
<tr>
<td>B#4&nbsp;</td>

или
Код

[пустая строка]
<tr class=ltr>
<td>B#3&nbsp;</td>

или
Код

[пустая строка]
<tr>
<td class=port>B#3&nbsp;</td>


Пошел от простого к сложному: 

$cnt = () = $str =~ m/^\<tr\sclass\=ltr\>$/gm; -- такую строку нахожу

$cnt = () = $str =~ m/^\<tr\sclass\=ltr\>$^\<td\>/gm; -- а такую уже нет.

Как обозначить перенос строки в регекспе?

Автор: alezzz 17.2.2011, 16:54
$^ -- это переменная в перл.

$cnt = () = $str =~ m/^<tr class=ltr>\n^<td>/gm;

Автор: arto 17.2.2011, 17:36
perl -0777 -lne 'my $cnt = () = m/\n(?:<tr>|<tr\s+class=ltr>)\n(?:<td>|<td\s+class=port>)B#/gs; print $cnt'  file

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)