online - regex tutorial




Regex para dividir etiquetas HTML (4)

Tengo una cadena HTML así:

<img src="http://foo"><img src="http://bar">

¿Cuál sería el patrón de expresiones regulares para dividir esto en dos etiquetas de img separadas?


Una manera un poco loca / brillante / extraña de hacerlo sería dividir en> <y luego agregar los dos caracteres hacia atrás respectivamente a la cadena después de la división.

$string = '<img src="http://foo"><img src="http://bar">';
$KimKardashian = split("><",$string);
$First = $KimKardashian[0] . '>';
$Second = '<' . $KimKardashian[1];

¿Qué tan seguro estás de que tu cuerda sea exactamente eso? ¿Qué tal una entrada como esta?

<img alt=">"          src="http://foo"  >
<img src='http://bar' alt='<'           >

¿Qué lenguaje de programación es este? ¿Hay alguna razón por la que no estés usando una clase estándar de análisis de HTML para manejar esto? Los regex son solo un buen enfoque cuando tienes un conjunto de entradas extremadamente conocido. No funcionan con HTML real, solo para demostraciones manipuladas.

Incluso si debe usar una expresión regular, debe usar una correcta gramatical. Esto es bastante fácil. He probado el siguiente programa en un trillón de páginas web. Se ocupa de los casos que describo arriba, y uno o dos más, también.

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

my $img_rx = qr{

    # save capture in $+{TAG} variable
    (?<TAG> (?&image_tag) )

    # remainder is pure declaration
    (?(DEFINE)

        (?<image_tag>
            (?&start_tag)
            (?&might_white) 
            (?&attributes) 
            (?&might_white) 
            (?&end_tag)
        )

        (?<attributes>
            (?: 
                (?&might_white) 
                (?&one_attribute) 
            ) *
        )

        (?<one_attribute>
            \b
            (?&legal_attribute)
            (?&might_white) = (?&might_white) 
            (?:
                (?&quoted_value)
              | (?&unquoted_value)
            )
        )

        (?<legal_attribute> 
            (?: (?&required_attribute)
              | (?&optional_attribute)
              | (?&standard_attribute)
              | (?&event_attribute)
              # for LEGAL parse only, comment out next line 
              | (?&illegal_attribute)
            )
        )

        (?<illegal_attribute> \b \w+ \b )

        (?<required_attribute>
            alt
          | src
        )

        (?<optional_attribute>
            (?&permitted_attribute)
          | (?&deprecated_attribute)
        )

        # NB: The white space in string literals 
        #     below DOES NOT COUNT!   It's just 
        #     there for legibility.

        (?<permitted_attribute>
            height
          | is map
          | long desc
          | use map
          | width
        )

        (?<deprecated_attribute>
             align
           | border
           | hspace
           | vspace
        )

        (?<standard_attribute>
            class
          | dir
          | id
          | style
          | title
          | xml:lang
        )

        (?<event_attribute>
            on abort
          | on click
          | on dbl click
          | on mouse down
          | on mouse out
          | on key down
          | on key press
          | on key up
        )

        (?<unquoted_value> 
            (?&unwhite_chunk) 
        )

        (?<quoted_value>
            (?<quote>   ["']      )
            (?: (?! \k<quote> ) . ) *
            \k<quote> 
        )

        (?<unwhite_chunk>   
            (?:
                # (?! [<>'"] ) 
                (?! > ) 
                \S
            ) +   
        )

        (?<might_white>     \s *   )

        (?<start_tag>  
            < (?&might_white) 
            img 
            \b       
        )

        (?<end_tag>          
            (?&html_end_tag)
          | (?&xhtml_end_tag)
        )

        (?<html_end_tag>       >  )
        (?<xhtml_end_tag>    / >  )

    )

}six;

$/ = undef;
$_ = <>;   # read all input

# strip stuff we aren't supposed to look at
s{ <!    DOCTYPE  .*?         > }{}sx; 
s{ <! \[ CDATA \[ .*?    \]\] > }{}gsx; 

s{ <script> .*?  </script> }{}gsix; 
s{ <!--     .*?        --> }{}gsx;

my $count = 0;

while (/$img_rx/g) {
    printf "Match %d at %d: %s\n", 
            ++$count, pos(), $+{TAG};
} 

Ahí tienes. ¡Nada para eso!

Vaya, ¿por qué querrías usar una clase de análisis de HTML, dada la facilidad con la que se puede tratar el HTML en una expresión regular? ☺


<img src=\"https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?\">

Ejemplo de PHP:

$prom = '<img src="http://foo"><img src="http://bar">';

preg_match_all('|<img src=\"https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?\">|',$prom, $matches);

print_r($matches[0]);

No lo hagas con regex . Use un analizador HTML / XML. Incluso puedes ejecutarlo a través de Tidy primero para limpiarlo. La mayoría de los idiomas tienen una biblioteca Tidy. Qué idioma estás usando?





regex