• Publicidad

Delimitar cadena por medio de dos palabras

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Delimitar cadena por medio de dos palabras

Notapor dandarc_perl » 2009-08-05 11:24 @517

Hola,
Quisiera saber si es posible delimitar una cadena por medio de dos palabras, por ejemplo, dada la siguiente cadena imprimir solo lo que se encuentra entre las palabras "aqui" y "fin":

Lo que aqui se muestra no se debe de imprimir, pero lo que aqui se muestra si se debe de imprimir fin pero esto de aqui tampoco y esto de aquí también se deberá imprimir fin

De tal manera que lo que el resultado al imprimir sea:

se muestra si se debe de imprimir también se deberá imprimir

Espero haberme explicado correctamente y me puedan ayudar.
Saludos.
Última edición por explorer el 2009-08-06 09:55 @455, editado 1 vez en total
Razón: Ortografía
dandarc_perl
Perlero nuevo
Perlero nuevo
 
Mensajes: 28
Registrado: 2008-08-13 17:55 @788

Publicidad

Re: Delimitar cadena por medio de dos palabras

Notapor preiddy » 2009-08-05 14:19 @638

Tuve un problema parecido y explorer me indicó este método en su momento.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while ( $_ =~ /(^palabra.+?^palabras *?$)/smg ){
    # Aquí pones lo que quieras
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
preiddy
Perlero nuevo
Perlero nuevo
 
Mensajes: 70
Registrado: 2006-03-29 05:43 @280
Ubicación: Madrid, España

Re: Delimitar cadena por medio de dos palabras

Notapor explorer » 2009-08-06 10:08 @464

Hay que hacer un bucle para extraer lo que hay entre las dos palabras, a lo largo de toda la cadena (/g):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while ( $_ =~ /palabra1(.+?)palabra2)/smg ) {
    print "$1\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Delimitar cadena por medio de dos palabras

Notapor dandarc_perl » 2009-08-06 11:25 @517

Gracias preiddy y explorer,
el ejemplo lo implemente así:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $cadena = "Lo que aqui se muestra no se debe de imprimir, pero lo que aqui se muestra si se debe de imprimir fin pero esto de aqui tampoco y esto de aqui también se deberá imprimir fin";
  2. while ( $cadena =~ /(aqui(.+?)fin)/smg ) {
  3.     print "$1\n";
  4. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


pero el resultado que me da es este:
aqui se muestra no se debe de imprimir, pero lo que aqui se muestra si se debe de imprimir fin
aqui tampoco y esto de aqui también se deberá imprimir fin

y el resultado esperado seria:
aqui se muestra si se debe de imprimir fin
aqui también se deberá imprimir fin


el código encuentra el primer "aqui" y a partir de ahí inicia la cadena, siendo que la cadena debe ser delimitada estrictamente entre las palabras "aqui" y "fin".
Si me pudieran explicar un poco el código que enviaron para ver si lo puedo adecuar a lo que necesito se los agradecería.
dandarc_perl
Perlero nuevo
Perlero nuevo
 
Mensajes: 28
Registrado: 2008-08-13 17:55 @788

Re: Delimitar cadena por medio de dos palabras

Notapor creating021 » 2009-08-06 22:45 @989

No es tan lindo como las expresiones regulares, pero funciona:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $cadena = "Lo que aqui se muestra no se debe de imprimir, pero lo que aqui se muestra si se debe de imprimir fin pero esto de aqui tampoco y esto de aqui también se deberá imprimir fin";
  2. my @palabras = split / /, $cadena;
  3. my $fin  = 0;
  4. my $aqui = 0;
  5. my $i    = 0;
  6. my @salida;
  7.  
  8. foreach my $palabra ( reverse @palabras ) {
  9.     if ( $aqui == 0 and $palabra eq "aqui" ) {
  10.         $fin = 0;
  11.         $aqui = 1;
  12.         push @{ $salida[$i++] }, "aqui";
  13.     }
  14.     elsif ( $fin == 0 and $palabra eq "fin" ) {
  15.         $aqui = 0;
  16.         $fin  = 1;
  17.         push @{ $salida[$i] }, "fin";
  18.     }
  19.     elsif ( $fin == 1 ) {
  20.         push @{$salida[$i]}, $palabra;
  21.     }
  22. }
  23.  
  24. for ( 0..$#salida ) {
  25.     print ( join " ", ( reverse @{ $salida[$_] } ) );
  26.     print "\n";
  27. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El truco es ir al último "fin" y retroceder hasta el "aqui" más cercano, espero que se te dé una idea.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Re: Delimitar cadena por medio de dos palabras

Notapor explorer » 2009-08-07 05:21 @265

El problema es que no está descrito bien el problema: nos están comentado que tenemos que sacar texto delimitado, pero que hay el problema de que el delimitador primero puede aparecer antes de lo que nos interesa.

Otro caso es que siempre apareciera, porque entonces sí que es fácil de resolver.

En cualquier caso, la solución sencilla es:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -l
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my $cadena = 'Lo que aqui se muestra no se debe de imprimir,
  7. pero lo que aqui se muestra sí se debe de imprimir fin
  8. pero esto de aqui tampoco y esto de aqui también se deberá imprimir fin';
  9.  
  10. print "[$cadena]\n";
  11.  
  12. use Regexp::Common qw/balanced/;
  13.  
  14. while ( $cadena =~ /$RE{balanced}{-begin=>'aqui'}{-end=>'fin'}{-keep}/g) {
  15.     print "[$1]";
  16. }
  17.  
  18. #print $RE{balanced}{-begin=>'aqui'}{-end=>'fin'};
  19. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Con un simple módulo de búsqueda de patrones con delimitadores balanceados, nos sirve. La salida es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
[Lo que aqui se muestra no se debe de imprimir,
pero lo que aqui se muestra sí se debe de imprimir fin
pero esto de aqui tampoco y esto de aqui también se deberá imprimir fin]

[aqui se muestra sí se debe de imprimir fin]
[aqui también se deberá imprimir fin]
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Eso sí, la expresión regular generada es bastante compleja (el último print comentado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
(?-xism:(?-xism:(?:aqui(?:(?>[^af]+)|a(?!qui)|f(?!in)|(??{$Regexp::Common::balanced [0]}))*fin)))
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

pero la solución la tenemos, así que... asunto solucionado.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Delimitar cadena por medio de dos palabras

Notapor explorer » 2009-08-07 13:09 @589

Bueno, he construido una simplificación de la expresión regular ofrecida por el módulo Regexp::Common.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -l
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my $cadena
  7.     = 'Lo que aqui se muestra no se debe de imprimir, '
  8.     . 'pero lo que aqui se muestra sí se debe de imprimir fin '
  9.     . 'pero esto de aqui tampoco y esto de aqui también se deberá imprimir fin'
  10.     ;
  11.  
  12. print "[$cadena]\n";
  13.  
  14. #use re 'debug';
  15.  
  16. while ($cadena =~
  17.     m/
  18.         \b aqui \b                  # El primer delimitador: la palabra 'aqui'
  19.  
  20.         (?:                         # Lo siguiente no nos interesa guardar
  21.  
  22.             (?>[^af]+ ) |           # Buscamos, hacia adelante, uno o más caracteres
  23.                                     # que no sean ni 'a' ni 'f'
  24.  
  25.             a(?!qui)    |           # pero si los encontramos, la 'a' no debe
  26.                                     # pertenecer a la palabra 'aqui'
  27.  
  28.             f(?!in)                 # y si es una 'f', no debe ser de la palabra 'fin'
  29.  
  30.         )*                          # 0 o más caracteres como los indicados antes
  31.  
  32.         \b fin \b                   # El segundo delimitador: la palabra 'fin'
  33.     /gmsx
  34. ) {
  35.     print "[$&]";                   # Pintamos lo encontrado
  36. }
  37.  
  38. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El resultado es el mismo que el anterior mensaje.
Última edición por explorer el 2009-08-07 14:00 @625, editado 4 veces en total
Razón: Mejor explicación de la expresión regular
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Delimitar cadena por medio de dos palabras

Notapor dandarc_perl » 2009-08-11 12:37 @567

Excelente como siempre, gracias explorer y también a creating021 que presentó una solución excelente también.

Gracias.
dandarc_perl
Perlero nuevo
Perlero nuevo
 
Mensajes: 28
Registrado: 2008-08-13 17:55 @788


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron