• Publicidad

Expresión regular de matching

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Expresión regular de matching

Notapor noballack » 2006-12-11 05:17 @261

buenas,

Hace días hice un post en el que pedía si alguien me podía ayudar con una expresión regular que descartara todos los links que tuvieran una palabra determinada, pues bien, la expresión que me distéis me sirvió de mucho y funciona a la perfección, pero resulta que ahora necesito todo lo contrario. Necesito una expresión regular que recoja todos los links que contengan una determinada palabra.

Ejemplo:
Código: Seleccionar todo
<a href="http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816">The Bottled Water Lie</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a>
<a href="http://money.cnn.com/data/afterhours/">Test</a>
<a href="http://money.cnn.com/popups/2006/moneymag/fivegifts/index.html">Test2</a>

Los 2 primeros son los links buenos, contienen la palabra "postversion".
La expresión de la que parto es esta:
Código: Seleccionar todo
$expresion =~ /<a href="((?:(?!video).)+)">([^\>]+)<\/a>/g;

Esta expresión es la que me disteis para coger todos los links que no contengan la palabra vídeo. He intentado hacer:
Código: Seleccionar todo
$expresion =~ /<a href="((?:(postversion).)+)">([^\>]+)<\/a>/g;


Pero evidentemente no funciona. ¿Me podéis ayudar?
Muchas gracias.

PD: Por cierto, los ':', ¿que significan?
noballack
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2006-11-02 10:09 @464

Publicidad

Notapor explorer » 2006-12-11 08:28 @394

La combinación '(?: ... )' indica que no son paréntesis de captura (lo que coincida dentro de ellos no será capturado para el exterior).

Esta expresión regular extrae los enlaces que quieres:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open LINKS,"<kk.txt" or die "Agg!: $!\n";
while ( $enlace = <LINKS> ) {
  if ( ( $link, $texto ) = $enlace =~ /href="(.*postversion.*)".*>(.*)<\/a>/ ) {
    print "Enlace: $link\nTexto: $texto\n";
  }
}
close LINKS;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Aquí buscamos texto alrededor de postversion y delimitado por las comillas dobles. Podemos usar los peligrosos '.*' ya que estamos seguros de que cada línea del fichero de entrada sólo contiene un enlace cada vez. Si no fuera así, habría que cambiarlos por '.*?'.

Pero quizás sea más claro dividir el problema:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open LINKS,"<kk.txt" or die "Agg!: $!\n";
while ( $enlace = <LINKS> ) {
  if ( ( $link, $texto ) = $enlace =~ /href="(.*)".*>(.*)<\/a>/ ) {
    print "Enlace: $link\nTexto: $texto\n" if $link =~ /postversion/;
  }
}
close LINKS;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Primero extraemos todo el enlace y su título correspondiente. El siguiente print se ejecuta si (if) el $link contiene la palabra que buscamos. Lo mismo que antes, estamos usando '.*' muy alegremente, pero es perfecto si la entrada está dentro de un formato bien claro.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor noballack » 2006-12-12 03:27 @185

Buenas,

Primero de todo dar la gracias a explorer por la explicación del '(?: ... )'.

He probado el código que me has propuesto para solucionar mi problema y funciona si sustituyo los peligrosos '.*' por '.*?' ya que no puedo asegurar que haya un link por línea. Como digo esto funciona muy bien si el juego de pruebas es este:
Código: Seleccionar todo
<a href="http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816">The Bottled Water Lie</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a>
<a href="http://money.cnn.com/data/afterhours/">Test</a>
<a href="http://money.cnn.com/popups/2006/moneymag/fivegifts/index.html">Test2</a>


resultado de aplicar la expresión regular:
Código: Seleccionar todo
link: http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816
texto: The Bottled Water Lie

link: http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817
texto: The Bottled Water Lie


Pero deja de funcionar si el juego de pruebas es este otro:
Código: Seleccionar todo
<a href="http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816">The Bottled Water Lie</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a>
<a href="http://money.cnn.com/data/afterhours/">Test</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a> <a href="http://money.cnn.com/popups/2006/moneymag/fivegifts/index.html">Test2</a>


El resultado que obtengo en este caso es:
Código: Seleccionar todo
link: http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816
texto: The Bottled Water Lie

link: http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817
texto: The Bottled Water Lie

link: http://money.cnn.com/data/afterhours/">Test</a> <a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817
texto: The Bottled Water Lie


Yo también pienso que la opción modificando el código fuente es la mejor, pero mi problema es que no puedo modificarlo. Debo hacerlo todo con la expresión regular.

Si os sirve de algo este es el código Perl que estoy utilizando para hacer las pruebas:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $links = qq{
<a href="http://money.cnn.com/2006/11/28/pf/heating_costs_savings/index.htm?postversion=2006112816">The Bottled Water Lie</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a>
<a href="http://money.cnn.com/data/afterhours/">Test</a>
<a href="http://money.cnn.com/2006/11/28/markets/markets_0545/index.htm?postversion=2006112817">The Bottled Water Lie</a> <a href="http://money.cnn.com/popups/2006/moneymag/fivegifts/index.html">Test2</a>
};


while ( $links =~ /href="(.*?postversion.*?)".*?>(.*?)<\/a>/isg) {
    my ($url, $title) = ($1, $2);
    print("$url : $title\n");
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
noballack
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2006-11-02 10:09 @464

Notapor explorer » 2006-12-12 05:00 @250

No entiendo que sólo puedas cambiar la expresión regular. Estás cambiando el código fuente de todas maneras.

Prueba con esta expresión regular:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$links =~ /href="([^"]*?postversion[^"]*?)".*?>(.*?)<\/a>/isg
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Estamos obligando a que postversion esté dentro de un único enlace (por algo son tan peligrosos los '.*' :-)).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor noballack » 2006-12-13 05:55 @288

Primero de todo, muchas gracias, ¡ahora sí que funciona a la perfección!

Y segundo, no puedo modificar el código fuente porqué la expresión proviene de una variable. El código fuente es fijo, no se puede tocar.

De nuevo muchas gracias. ¡Hasta pronto!
noballack
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2006-11-02 10:09 @464


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados