Как я могу удалить каждый третий HTML-тег в Perl? - PullRequest
4 голосов
/ 16 марта 2009

Это быстро готовый скрипт, но у меня возникли некоторые трудности из-за незнакомства с регулярными выражениями и Perl.

Скрипт должен читаться в HTML-файле. В файле (само по себе) есть место, где у меня есть куча

с. Я хочу удалить каждую треть из них - они сгруппированы в четверки.

Мой скрипт ниже не скомпилируется, не говоря уже о запуске.

#!/usr/bin/perl
use warnings;
use strict;


&remove();

sub remove {
    my $input = $ARGV[0];
    my $output = $ARGV[1];
    open INPUT, $input or die "couldn't open file $input: $!\n";
    open OUTPUT, ">$output" or die "couldn't open file $output: $!\n";

    my @file = <INPUT>;
    foreach (@file) {
        my $int = 0;
        if ($_ =~ '<div class="cell">') {
        $int++;
        { // this brace was the wrong way
        if ($int % 4 == 3) {
        $_ =~ '/s\<div class="cell">\+.*<\/div>/;/g';
            }
    }
    print OUTPUT @file;
}

Спасибо за вашу помощь. Я знаю, что неправильно анализировать регулярные выражения, но я просто хочу, чтобы это сработало.

После смерти: проблема почти решена. И мне стыдно тех, кто сказал мне, что регулярное выражение не годится - я знал это с самого начала. Но опять же, я хотел чего-то быстрого и запрограммировал XSLT, который это произвел. В этом случае у меня не было источника, чтобы запустить его снова, иначе я бы запрограммировал его в XSLT.

Ответы [ 5 ]

4 голосов
/ 16 марта 2009

Я согласен, что HTML не может быть проанализирован регулярными выражениями, но для быстрых небольших взломов HTML, формат которого вы знаете, регулярные выражения работают отлично. Хитрость в замене повторений регулярным выражением состоит в том, чтобы поместить повторение в регулярное выражение. Если вы этого не сделаете, у вас возникнут проблемы с синхронизацией позиции сопоставителя регулярных выражений с вводом, который вы читаете.

Вот быстрый и грязный способ, которым я бы написал Perl. Он удаляет третий элемент div, даже если он вложен в первые два элемента div. Весь файл читается, а затем я использую модификатор глобальной замены g, чтобы регулярное выражение выполняло подсчет. Если вы раньше не видели модификатор «x», все, что он делает, это позволяет вам добавлять пробелы для форматирования - пробелы игнорируются в регулярном выражении.

remove(@ARGV);

sub remove {
  my ($input, $output) = @_;

  open(INPUT, "<", $input) or die "couldn't open file $input: $!\n";
  open(OUTPUT, ">", $output) or die "couldn't open file $output: $!\n";

  my $content = join("", <INPUT>);
  close(INPUT);

  $content =~ s|(.*? <div \s+ class="cell"> .*? <div \s+ class="cell"> .*?)
                <div \s+ class="cell"> .*? </div>
                (.*? <div \s+ class="cell">)|$1$2|sxg;

  print OUTPUT $content;
  close OUTPUT;
}
3 голосов
/ 16 марта 2009

Если ваш код не компилируется, прочтите сообщения об ошибках и предупреждения. Если это не имеет смысла, обратитесь к perldoc perldiag (или поставить "использовать диагностику"; в вашем коде, чтобы автоматически сделать это для вас).

2 голосов
/ 16 марта 2009

Как только вы получите волнистые скобки, совпадающие друг с другом, и начнете правильно использовать регулярное выражение замещения, вам также нужно переместить

my $int = 0;

вне цикла for - в настоящее время он сбрасывается для каждой прочитанной строки, поэтому он будет иметь значение 0 или 1.

2 голосов
/ 16 марта 2009

Ну, вы правы, что вам не следует разбирать HTML с помощью регулярных выражений. И поскольку это так, то, вероятно, это не будет «просто работать».

В идеале вам нужно использовать HTML-библиотеку для анализа и манипулирования. Не думайте, что HTML - это большая строка для манипулирования текстовыми функциями: это сериализованная, отформатированная структура данных. Вы должны использовать только , используя библиотеку для этой цели. Различные библиотеки уже исправили сотни ошибок, с которыми вы, вероятно, столкнетесь, что в миллион раз повышает вероятность того, что простая процедура HTML-манипуляции, написанная против них, будет «просто работать». Программисты Perl на уровне мастера, как правило, не разбирают HTML таким образом, и это не потому, что они одержимы и иррациональны в отношении качества и чистоты кода, а потому, что они знают, что новое изобретение колеса вряд ли приведет к чему-то столь же гладкому, как существующее оборудование.

Я рекомендую HTML :: Tree, потому что он работает так, как я думаю о HTML (и XML). Я думаю, что есть пара других библиотек, которые могут быть более популярными.

Настоящая правда в том, что если вы даже не можете заставить свою программу скомпилировать , вам нужно потратить немного больше времени (примерно полдня), чтобы выяснить основы, прежде чем искать Помогите. В вашем синтаксисе есть ошибка при использовании оператора подстановки регулярного выражения s /// g, и вам нужно выяснить, как это должно работать, прежде чем идти дальше. Это не сложно, и вы можете узнать, что вам нужно, из книги Camel, или из справочника perlretut, или из нескольких других источников. Если вы не научитесь отлаживать свою программу сейчас, то, скорее всего, любая помощь, которую вы здесь получите, просто приведет вас к следующей синтаксической ошибке, которую вы не сможете устранить.

1 голос
/ 16 марта 2009

Подпрограмма заблудилась. Начнем с рассмотрения структуры этого:

sub remove {                                   # First opening bracket
    my $input = $ARGV[0];
    my $output = $ARGV[1];
    open INPUT, $input or die "couldn't open file $input: $!\n";
    open OUTPUT, ">$output" or die "couldn't open file $output: $!\n";

    my @file = <INPUT>;
    foreach (@file) {                          # Second opening bracket
        my $int = 0;
        if ($_ =~ '<div class="cell">') {      # Third opening bracket
        $int++;
        {                                      # Fourth opening bracket
        if ($int % 4 == 3) {                   # Fifth opening bracket
        $_ =~ '/s\<div class="cell">\+.*<\/div>/;/g';
            }                                  # First closing bracket
    }                                          # Second closing bracket
    print OUTPUT @file;
}                                              # Third closing bracket
                                               # No fourth closing bracket?
                                               # No fifth closing bracket?

Я думаю, вы хотели это:

sub remove {
    my $input = $ARGV[0];
    my $output = $ARGV[1];
    open INPUT, $input or die "couldn't open file $input: $!\n";
    open OUTPUT, ">$output" or die "couldn't open file $output: $!\n";

    my @file = <INPUT>;
    foreach (@file) {
        my $int = 0;
        if ($_ =~ '<div class="cell">') {
          $int++;
        }
        if ($int % 4 == 3) {
          $_ =~ '/s\<div class="cell">\+.*<\/div>/;/g';
        }
    }
    print OUTPUT @file;
}

Это скомпилирует и перенесет нас к следующему вопросу: почему вы пишете в кавычках регулярное выражение? (Также см. Замечание Себжира о размещении my $int = 0.)

(Чтобы понять точку Ysth, вы также всегда можете запустить скрипт с perl -Mdiagnostics script-name, чтобы получить более длинные диагностические сообщения.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...