كيف يمكنني استبدال كلمات متعددة، كل منها مجزأة إلى كلمة بديلة، في سمة HTML باستخدام Perl regex؟

StackOverflow https://stackoverflow.com/questions/1217068

  •  07-07-2019
  •  | 
  •  

سؤال

أنا أكتب أداة تشويش HTML، ولدي تجزئة تربط الأسماء سهلة الاستخدام (من المعرفات والفئات) بالأسماء المبهمة (مثل a وb وc وما إلى ذلك).أواجه مشكلة في التوصل إلى تعبير عادي لإنجاز استبدال شيء مثل

<div class="left tall">

مع

<div class="a b">

إذا كانت العلامات تقبل فئة واحدة فقط، فسيكون التعبير العادي ببساطة شيء من هذا القبيل

s/(class|id)="(.*?)"/$1="$hash{$2}"/

كيف يمكنني تصحيح هذا لحساب أسماء فئات متعددة ضمن علامات الاقتباس؟ويفضل أن يكون الحل متوافقًا مع لغة Perl.

هل كانت مفيدة؟

المحلول

وأعتقد أنني سأفعل هذا:

s/  
    (class|id)="([^"]+)"
/   
    $1 . '="' . (
        join ' ', map { $hash{$_} } split m!\s+!, $2
    ) . '"'
/ex;

نصائح أخرى

لا يجب أن تستخدم التعبير العادي لهذا في المقام الأول.أنت تحاول أن تفعل الكثير باستخدام تعبير عادي واحد (انظر هل يمكنك تقديم بعض الأمثلة عن سبب صعوبة تحليل XML وHTML باستخدام التعبير العادي؟ لماذا).ما تحتاجه هو محلل HTML.يرى هل يمكنك تقديم مثال لتحليل HTML باستخدام المحلل اللغوي المفضل لديك؟ للحصول على أمثلة باستخدام مجموعة متنوعة من المحللين.

نلقي نظرة على HTML::Parser.فيما يلي تنفيذ، ربما غير مكتمل:

#!/usr/bin/perl

use strict;
use warnings;

use HTML::Parser;

{
    my %map = (
        foo => "f",
        bar => "b",
    );

    sub start {
        my ($tag, $attr) = @_;
        my $attr_string = '';
        for my $key (keys %$attr) {
            if ($key eq 'class') {
                my @classes = split " ", $attr->{$key};
                #FIXME: this should be using //, but
                #it is only availble starting in 5.10
                #so I am using || which will do the
                #wrong thing if the class is 0, so
                #don't use a class of 0 in %map , m'kay
                $attr->{$key} = join " ", 
                    map { $map{$_} || $_ } @classes;
            }
            $attr_string .= qq/ $key="$attr->{$key}"/;
        }

        print "<$tag$attr_string>";
    }
}

sub text {
    print shift;
}

sub end {
    my $tag = shift;
    print "</$tag>";
}

my $p = HTML::Parser->new(
    start_h => [ \&start, "tagname,attr" ],
    text_h  => [ \&text, "dtext" ],
    end_h   => [ \&end, "tagname" ],
);

$p->parse_file(\*DATA);

__DATA__
<html>
    <head>
        <title>foo</title>
    </head>
    <body>
        <span class="foo">Foo!</span> <span class="bar">Bar!</span>
        <span class="foo bar">Foo Bar!</span>
        This should not be touched: class="foo"
    </body>
</html>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top