Como faço para substituir várias palavras, cada um hash de uma palavra alternativa, em um atributo HTML usando Perl regex?

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

  •  07-07-2019
  •  | 
  •  

Pergunta

Eu estou escrevendo um obfuscator HTML, e eu tenho um hash correlacionar nomes amigáveis ??(de ids e classes) para nomes ofuscado (como a, b, c, etc). Estou tendo dificuldades para chegar com uma expressão regular para realizar substituindo algo como

<div class="left tall">

com

<div class="a b">

Se marcas só poderia aceitar uma classe, a regexp seria simplesmente algo como

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

Como devo corrigir isso conta para para vários nomes de classe dentro de citações? De preferência, a solução deve ser Perl compatível.

Foi útil?

Solução

Eu acho que eu faria isso:

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

Outras dicas

Você não deve estar usando um regex para isso em primeiro lugar. Você está tentando fazer muito com um regex (ver Você pode fornecer alguns exemplos de por que é difícil para XML de análise e HTML com um regex? por que). O que você precisa é um analisador HTML. Consulte Você pode fornecer um exemplo de análise de HTML com o seu analisador favorita? para exemplos usando uma variedade de analisadores.

Dê uma olhada HTML::Parser . Aqui está uma, provavelmente incompleta, a implementação:

#!/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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top