Xpoint
   [напомнить пароль]

Script regexp

Метки: [без меток]
2004-07-07 17:18:08 [обр] Кирилл[досье]
Хочется регексп, который выделяет скрипты в html. Конструкция /(<script.*?<\/script>)/isg работает замечательно, однако хочется большего. А именно выделить только скрипты, которые содержат, скажем, ".write".
/(<script.*?\.write.*?<\/script>)/isg работает уже не так, как хотелось бы, а прихватывает еще лишние куски
(экспериментировал на www.rambler.ru, регексп прихватывает предыдущий скрипт и текст между ними)
Посоветуете что-нибудь? Нужет именно регексп, парсить html построчно в данном случае не подходит.
спустя 8 минут [обр] Алексей Севрюков(45/1292)[досье]
Может
m#<script[^>]*>.*?write.*?</script>#isg
спустя 7 минут [обр] Алексей В. Иванов(17/2861)[досье]
Кирилл[досье] Вам всего-то надо сначала все скрипты получить с помощью первой конструкции, а уже по получившемуся массиву пройтись и посмотреть есть ли там "write"
спустя 15 минут [обр] Алексей Севрюков(45/1292)[досье]
Алексей В. Иванов[досье] Согласен, это будет быстрее.
Кирилл[досье]
if($str=~m#<script[^>]*>(.*?)</script>#isg){
my $script=$1;
if($script=~m#write#){ # или document\.write
# Есть write в скрипте
}
}
спустя 25 минут [обр] Кирилл[досье]
К сожалению, регексп нужен не в perl. Есть такой content filter proxy Privoxy (http://www.privoxy.org/), там с помощью регекспов можно регулировать содержание html. Я понимаю, что не совсем топик, однако где еще можно найти знатоков регекспов? ;)
Но и с точки зрения перла (я на нем тестю регекспы) мне не совсем понятна ситуация:
если парсить с /(<script.*?<\/script>)/isg - скрипты хорошо выделяются. Если поменять на /(<script.*?write)/isg, тогда прихватывается и предыдущий скрипт. Почему во втором случае .*? значительно больше (и "?" не ограничивает жадность), чем в первом случае и можно ли на это повлиять (кроме как .{x,y}?) ? (Напомню: тестовый паттерн http://www.rambler.ru/)
спустя 27 минут [обр] Алексей Севрюков(45/1292)[досье]
Кирилл[досье] Ну ведь алгоритмы регулок то разные в природе существует. ПОтому в перле например это может работать, а где-то еще нет. В некоторых алгоритмах вообще нет минимальных квантификаторов.
спустя 1 час 10 минут [обр] Alexander O(44/469)[досье]

Кирилл[досье]
Я бы написал так:

/<script[^>]*>(?:[^<w]*)(?:(?:<(?!\/script)|w(?!rite))(?:[^<w]*))*write(?:[^<]*<(?!=\/script))+\/script>/

если не схавает, то так:

/<script[^>]*>([^<w]*)((<(?!\/script)|w(?!rite))([^<w]*))*write([^<]*<(?!=\/script))+\/script>/
спустя 28 минут [обр] Алексей Севрюков(45/1292)[досье]
Alexander O[досье] вполне возможно что в том алгоритме нет ретроспективной проверки, надо проверять сперва по мелким кусочкам какие возможности есть, а потом уже строить регулку.
спустя 53 минуты [обр] Alexander O(44/469)[досье]

Алексей Севрюков[досье]
Кирилл же дал ссылку на Privoxy, где написано, что:

Privoxy uses Perl-style "regular expressions" in its actions files and filter file, through the PCRE and PCRS libraries.
...
 More reading on Perl Compatible Regular expressions: http://www.perldoc.com/perl5.6/pod/perlre.html

можно считать, что регулярные выражения совместимы с perl 5.6

спустя 17 часов [обр] Кирилл[досье]
Проблема не в privoxy. Я про него написал, чтобы объяснить, почему мне нужен именно регексп.
Проблема заключается в следующем коде:
#!/usr/bin/perl
$data = "<script ><!-- // --></script>
<SCRIPT LANGUAGE=JavaScript>
<!-- document.write('test \n'); //-->
</SCRIPT>";
$data =~ /(<script.*?write)/is;
print "$1\n";
Выводятся оба скрипта, а не последний, как можно было предположить. Почему?
спустя 8 минут [обр] Владимир Палант(98/4445)[досье]
Потому что Perl всегда ищет первую позицию, к которой подходит регулярное выражение. В отличие от жадности регулярного выражения (она решает, где будет конец найденого текста) это поведение не меняется. В данном случае можно лишь сделать так, чтобы в .*? не попал конец скрипа - это делает Alexander O[досье] в своем примере.
спустя 2 часа 40 минут [обр] Алексей Севрюков(45/1292)[досье]
Alexander O[досье] молчу, пропустил.
спустя 6 часов [обр] arty(0/6)[досье]
$data =~ /(<script(?:(?!<script).)*?write.*?<\/script>)/is;
работает
privoxy - отличная штука : )
спустя 10 часов [обр] Владимир Палант(98/4445)[досье]

arty[досье]
Может все-таки так:

/(<script(?:(?!<\/script).)*?write.*?<\/script>)/is

А то ведь и такое бывает:

<script>
var a='<script>';
document.write(a);
</script>
спустя 1 час 12 минут [обр] Alexander O(44/469)[досье]
arty[досье], Владимир Палант[досье]
вот вам html-бомба весом 20kb, не термоядерная, правда
#!perl -w

$| = 1;

print "wait please\n";

my $pid = fork;
die "Can't fork $!" unless defined $pid;

unless ($pid) {
    my $t = 1;
    print "\r$t sec" while $t++, sleep 1;
}
else {
    my $data = '<script>write</scrip' x 1024; # html-bomb
    $data =~ m{(<script(?:(?!<\/script).)*?write.*?<\/script>)}is;
    print "\nfinished\n";
    kill 'TERM' => $pid;
}
спустя 1 день 15 часов [обр] Дмитрий Котеров(21/912)[досье]
Тщетно пытался на протяжение 5 минут понять, зачем это все. Что за html-бомба такая, раз в браузер даже ни одного тэга не выводится? Это уж тогда perl-бомба будет.
спустя 6 часов [обр] Alexander O(44/469)[досье]
Дмитрий Котеров[досье] html-бомба, это то, чем подрывают браузеры, она не обязательно должна, что-нибудь показывать, главное, чтоб браузер грохнулся. С таким регэкспом грохнется (ну, будет тормозить) privoxy. Но, конечно, я привел это лишь ради шутки, - в интернете пользователь на такие странички не наткнется
спустя 5 часов [обр] Дмитрий Котеров(21/912)[досье]
Вот я и не понимаю, как браузер от данного скрипата может "грохнуться". Скрипт ведь просто печатает последовательно "1 sec, 2 sec" и т.д., а в конце - "finished".
спустя 5 часов [обр] Alexander O(44/469)[досье]

Дмитрий Котеров[досье] не от скрипта, от статического неправильного html

<html>
<script>write</scrip<script>write</scrip<script>write</scrip
<script>write</scrip<script>write</scrip<script>write</scrip
<script>write</scrip<script>write</scrip<script>write</scrip
...
<script>write</scrip<script>write</scrip<script>write</scrip
</html>

а скрипт лишь иллюстрирует, он выступает, как бы, в роли privoxy, получаюшего такую страницу. А секунды будет считать пользователь, смотря в пустое окошко браузера.
Privoxy в это время будет выполнять операцию, которую в Perl можно записать как $html_page =~ s{(<script(?:(?!<\/script).)*?write.*?<\/script>)}{}is;

Powered by POEM™ Engine Copyright © 2002-2005