Página 1 de 1

Búsqueda de expresiones en una secuencia

NotaPublicado: 2009-08-18 14:48 @658
por principiante
Tengo que hacer un programa que dada una secuencia busque si contiene una expresión que es introducida por el usuario desde teclado. Se tiene que obtener también la posición de inicio y final de esa expresión en la secuencia cada vez que aparezca esa expresión.

Tengo el siguiente código
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2. use strict;
  3. use warnings;
  4.  
  5. my $sec = 'SXRDCTFFFFFYVGUBHNJKLFVNLAISUBNLASDIUV
  6. ÑSDVFNÑASNVÑAJSDBNÑFOIVABNÑSDFVBGÑASOI
  7. OUIBHVDUIOAEIRVCTFFFFFFFFFBIÑSDAUBGPEWIUBVÑWEOPINGVÑER
  8. EOVUNHOWUIGNÑVWUvÑBNVPIUWBNVIPUWBPIVÑBN
  9. DUIVOWPIER';
  10. my $expr;
  11.  do {
  12.     print "Introduzca la expresión regular a buscar: ";
  13.     $expr = <STDIN>;
  14.     chomp $expr;
  15.    
  16.     if ($sec =~ /$expr/) {  
  17.         my $inicio = index ($sec,$expr);
  18.         while ($inicio != -1){  
  19.                 my $fin = $inicio + length($expr);
  20.                 print "$inicio\t$fin\t$expr\n";
  21.                 my $contador = $inicio + length($expr);
  22.                 $inicio = index ($sec,$expr,$contador);        
  23.         }
  24.        
  25.     } else {
  26.         print "No aparece\n";
  27.     }
  28.  
  29.  }until ($expr =~ /^\s*$/);
  30.  
  31. # exit the program
  32. exit;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


si se busca "CTF" se obtiene:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Introduzca la expresión regular: CTF
4       7       CTF
99      102     CTF
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


NO obtengo la posición de inicio de la expresión CTF si no la posición justo anterior a la letra C.

Y si la expresión a buscar es "CT(F){3,}" [CT seguido de 3 o más F] no obtengo nada

¿¿Cómo podría solucionar este problema??

Re: Búsqueda de expresiones en una secuencia

NotaPublicado: 2009-08-18 20:24 @892
por explorer
Las posiciones de los caracteres dentro de una cadena se numeran de la misma manera que los índices de los arreglos: desde cero. Por eso, tus operaciones de búsqueda devuelven un 4: porque la expresión se ha encontrado en la quinta posición.

Esta es una versión más simplificada: usa la función pos() para saber dónde ha terminado la expresión encontrada, usa $& para saber qué expresión se ha encontrado, y se hace un bucle while() con la expresión regular, junto con el modificador /g, para que repita la búsqueda por toda la secuencia. Fíjate cómo, además, añado un +1 para pasar a posiciones reales (basadas en 1, no en 0). Y un detalle cuando se pinta el aviso de que no se ha encontrado: se usa un and para concatenar (y ejecutar) dos acciones si se cumple la condición.

Atención que en tu código hay un posible error: has puesto la secuencia como varias líneas de texto. Podría darse el caso de que quieras buscar por una expresión que se encontrase entre dos líneas -por ejemplo, OIOU-. Si no ponemos la expresión regular de la línea 12 que une todas las líneas en una sola, nos dirá que no aparece, pero con ella, nos indica que está en la posición 81.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my $sec = 'SXRDCTFFFFFYVGUBHNJKLFVNLAISUBNLASDIUV
  7. ÑSDVFNÑASNVÑAJSDBNÑFOIVABNÑSDFVBGÑASOI
  8. OUIBHVDUIOAEIRVCTFFFFFFFFFBIÑSDAUBGPEWIUBVÑWEOPINGVÑER
  9. EOVUNHOWUIGNÑVWUvÑBNVPIUWBNVIPUWBPIVÑBN
  10. DUIVOWPIER';
  11.  
  12. $sec =~ s/\n//g;  # Unimos todas las líneas
  13.  
  14. while (1) {
  15.     print "Introduzca la expresión regular a buscar: ";
  16.     chomp(my $expr = <>);
  17.     last if $expr =~ /^$/;  # Salimos con un 'enter'
  18.  
  19.     print "No aparece\n" and next if $sec !~ /$expr/;
  20.  
  21.     while ($sec =~ /$expr/gi) {
  22.         my $fin = pos($sec) + 1;
  23.         my $inicio = $fin - length $&;
  24.         print "$inicio\t$fin\t$&\n";
  25.     }
  26. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


No obtienes un valor cuando buscas por CTF{3,} porque estás usando la función index(), que no sirve con expresiones regulares. Solo funcione con cadenas de texto. Por eso, con CTF sí que funciona. Con CTF{3,} está buscando exactamente eso (incluidas las llaves).

Otra forma de escribir una secuencia larga de caracteres, sin los retornos de carro, puede ser así, usando el operador de concatenación:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $sec
    = 'SXRDCTFFFFFYVGUBHNJKLFVNLAISUBNLASDIUV'
    . 'ÑSDVFNÑASNVÑAJSDBNÑFOIVABNÑSDFVBGÑASOI'
    . 'OUIBHVDUIOAEIRVCTFFFFFFFFFBIÑSDAUBGPEWIUBVÑWEOPINGVÑER'
    . 'EOVUNHOWUIGNÑVWUvÑBNVPIUWBNVIPUWBPIVÑBN'
    . 'DUIVOWPIER'
    ;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Búsqueda de expresiones en una secuencia

NotaPublicado: 2009-08-19 03:46 @198
por principiante
¿¿Cómo podría hacer para que el programa buscase también las expresiones introducidas en minúsculas??

Es decir, que buscase expresiones en minúsculas aunque la secuencia esté en mayúsculas.

Por ejemplo:

Al buscar CTF Y ctf se obtuviera el mismo resultado de búsqueda.

No sé si queda muy claro...

Re: Búsqueda de expresiones en una secuencia

NotaPublicado: 2009-08-19 05:17 @262
por principiante
Ya he solucionado mi duda. Muchas gracias por todo, explorer.

Re: Búsqueda de expresiones en una secuencia

NotaPublicado: 2009-08-19 06:17 @303
por explorer
Basta con poner la opción /i en la expresión regular. Ya está el código cambiado.