Script regexp
Метки: [без меток]
Хочется регексп, который выделяет скрипты в html. Конструкция /(<script.*?<\/script>)/isg работает замечательно, однако хочется большего. А именно выделить только скрипты, которые содержат, скажем, ".write".
/(<script.*?\.write.*?<\/script>)/isg работает уже не так, как хотелось бы, а прихватывает еще лишние куски
(экспериментировал на www.rambler.ru, регексп прихватывает предыдущий скрипт и текст между ними)
Посоветуете что-нибудь? Нужет именно регексп, парсить html построчно в данном случае не подходит.
/(<script.*?\.write.*?<\/script>)/isg работает уже не так, как хотелось бы, а прихватывает еще лишние куски
(экспериментировал на www.rambler.ru, регексп прихватывает предыдущий скрипт и текст между ними)
Посоветуете что-нибудь? Нужет именно регексп, парсить html построчно в данном случае не подходит.
Кирилл[досье] Вам всего-то надо сначала все скрипты получить с помощью первой конструкции, а уже по получившемуся массиву пройтись и посмотреть есть ли там "write"
К сожалению, регексп нужен не в perl. Есть такой content filter proxy Privoxy (http://www.privoxy.org/), там с помощью регекспов можно регулировать содержание html. Я понимаю, что не совсем топик, однако где еще можно найти знатоков регекспов? ;)
Но и с точки зрения перла (я на нем тестю регекспы) мне не совсем понятна ситуация:
если парсить с /(<script.*?<\/script>)/isg - скрипты хорошо выделяются. Если поменять на /(<script.*?write)/isg, тогда прихватывается и предыдущий скрипт. Почему во втором случае .*? значительно больше (и "?" не ограничивает жадность), чем в первом случае и можно ли на это повлиять (кроме как .{x,y}?) ? (Напомню: тестовый паттерн http://www.rambler.ru/)
Но и с точки зрения перла (я на нем тестю регекспы) мне не совсем понятна ситуация:
если парсить с /(<script.*?<\/script>)/isg - скрипты хорошо выделяются. Если поменять на /(<script.*?write)/isg, тогда прихватывается и предыдущий скрипт. Почему во втором случае .*? значительно больше (и "?" не ограничивает жадность), чем в первом случае и можно ли на это повлиять (кроме как .{x,y}?) ? (Напомню: тестовый паттерн http://www.rambler.ru/)
Кирилл[досье] Ну ведь алгоритмы регулок то разные в природе существует. ПОтому в перле например это может работать, а где-то еще нет. В некоторых алгоритмах вообще нет минимальных квантификаторов.
Кирилл[досье]
Я бы написал так:
/<script[^>]*>(?:[^<w]*)(?:(?:<(?!\/script)|w(?!rite))(?:[^<w]*))*write(?:[^<]*<(?!=\/script))+\/script>/
если не схавает, то так:
/<script[^>]*>([^<w]*)((<(?!\/script)|w(?!rite))([^<w]*))*write([^<]*<(?!=\/script))+\/script>/
Alexander O[досье] вполне возможно что в том алгоритме нет ретроспективной проверки, надо проверять сперва по мелким кусочкам какие возможности есть, а потом уже строить регулку.
Алексей Севрюков[досье]
Кирилл же дал ссылку на 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
Проблема не в privoxy. Я про него написал, чтобы объяснить, почему мне нужен именно регексп.
Проблема заключается в следующем коде:
#!/usr/bin/perl
$data = "<script ><!-- // --></script>
<SCRIPT LANGUAGE=JavaScript>
<!-- document.write('test \n'); //-->
</SCRIPT>";
$data =~ /(<script.*?write)/is;
print "$1\n";
Выводятся оба скрипта, а не последний, как можно было предположить. Почему?
Проблема заключается в следующем коде:
#!/usr/bin/perl
$data = "<script ><!-- // --></script>
<SCRIPT LANGUAGE=JavaScript>
<!-- document.write('test \n'); //-->
</SCRIPT>";
$data =~ /(<script.*?write)/is;
print "$1\n";
Выводятся оба скрипта, а не последний, как можно было предположить. Почему?
Потому что Perl всегда ищет первую позицию, к которой подходит регулярное выражение. В отличие от жадности регулярного выражения (она решает, где будет конец найденого текста) это поведение не меняется. В данном случае можно лишь сделать так, чтобы в .*? не попал конец скрипа - это делает Alexander O[досье] в своем примере.
$data =~ /(<script(?:(?!<script).)*?write.*?<\/script>)/is;
работает
privoxy - отличная штука : )
работает
privoxy - отличная штука : )
arty[досье]
Может все-таки так:
/(<script(?:(?!<\/script).)*?write.*?<\/script>)/is
А то ведь и такое бывает:
<script> var a='<script>'; document.write(a); </script>
arty[досье], Владимир Палант[досье]
вот вам html-бомба весом 20kb, не термоядерная, правда
вот вам 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; }
Тщетно пытался на протяжение 5 минут понять, зачем это все. Что за html-бомба такая, раз в браузер даже ни одного тэга не выводится? Это уж тогда perl-бомба будет.
Дмитрий Котеров[досье] html-бомба, это то, чем подрывают браузеры, она не обязательно должна, что-нибудь показывать, главное, чтоб браузер грохнулся. С таким регэкспом грохнется (ну, будет тормозить) privoxy. Но, конечно, я привел это лишь ради шутки, - в интернете пользователь на такие странички не наткнется
Вот я и не понимаю, как браузер от данного скрипата может "грохнуться". Скрипт ведь просто печатает последовательно "1 sec, 2 sec" и т.д., а в конце - "finished".
Дмитрий Котеров[досье] не от скрипта, от статического неправильного 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;