• Publicidad

Reconocer y contabilizar caracteres

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

Reconocer y contabilizar caracteres

Notapor koolik » 2012-04-21 17:52 @786

Hola a todos. Deseo identificar las 'a' y las 'b' de la cadena para imprimirlas y contarlas.
Ejemplo:

Entrada: aababaabb\n

Salida a[2]baba[2]b[2]\n

Entrada: aaaab\n\n

Salida: a[3]b\n\n

Es decir, si hay una 'a' o 'b', despliega la letra; si hay más de una 'a' o 'b', además de la letra despliega la cantidad en corchetes.

Además debo desplegar la cantidad de líneas en blanco que haya.

He hecho algo así, pero no funciona
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while (<>)
  2. {
  3.         if (/( ( (a*)(b*) | (b*)(a*))(\n*) )/gm)
  4.         {
  5.             print "$3"; print "\n";
  6.                 print "$4"; print "\n";
  7.                 print "$5"; print "\n";
  8.                 print "$6"; print "\n";
  9.                
  10.                 if (($3) || ($6))
  11.                 {
  12.                         print "1";
  13.                 }      
  14.                 if (length($3) > 1)
  15.                 {
  16.                         print "<"; print length($3);print ">";
  17.                 }
  18.                 if (length($6) > 1)
  19.                 {
  20.                         print "<"; print length($6);print ">";
  21.                 }
  22. ::::; sigue algo similar
  23.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Les agradezco cualquier ayuda. Saludos.
Última edición por explorer el 2012-04-21 17:57 @789, editado 1 vez en total
Razón: Marcas de código Perl
koolik
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2012-04-21 17:42 @779

Publicidad

Re: Reconocer y contabilizar caracteres

Notapor explorer » 2012-04-21 18:05 @795

Bienvenido a los foros de Perl en Español, koolik.

El primer fallo que veo es que has puesto espacios en blanco dentro de la expresión regular.
Si la entrada es solo de letras 'a' y 'b', ese patrón no reconocerá ningún caso.
Una de dos: o agregas la opción '/x' al final de la expresión regular, o quitas los espacios en blanco del patrón.
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

Re: Reconocer y contabilizar caracteres

Notapor koolik » 2012-04-21 18:45 @823

Gracias por la bienvenida :)

He quitado los espacios y es lo mismo... sigue sin reconocer bien.

Con esta corrección, reconoce el patrón de las tiras bbaaa pero no los fin de línea.
Estoy haciendo de a poco, no entiendo por qué no reconoce los "\n".

Disculpa la clase de preguntas, pero nuevo total.
¡Saludos y gracias!


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. if (/((b+)(a+))(|\n+)/sgm)
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2012-04-22 05:19 @263, editado 1 vez en total
Razón: Marcas de código Perl
koolik
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2012-04-21 17:42 @779

Re: Reconocer y contabilizar caracteres

Notapor explorer » 2012-04-22 06:35 @316

Para detectar líneas en blanco, necesitas un patrón como este: /(\n\n+)/.

Un solo "\n" detecta el fin de línea de todas las líneas, pero lo importante es ver qué línea no tiene nada (excepto el propio carácter de fin de línea).

Con ese patrón, podemos saber el número de líneas en blanco haciendo un length($1)-1 (hay que descontar el primer "\n").
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Modern::Perl '2012';        # Somos modernos
  3. use utf8::all;                  # Turn on UTF-8. All of it.
  4. my $pruebas = <<EOF;
  5. aababaabb
  6. aaaab
  7.  
  8. ababbabbababbbbbbababbabba
  9.  
  10. aaaaaabbbbbb
  11. EOF
  12.  
  13. my $número_líneas_en_blanco = 0;
  14.  
  15. while ($pruebas =~ /(\n\n+)/gsm) {
  16.     $número_líneas_en_blanco += length($1) - 1;
  17. }
  18.  
  19. say "Número de líneas en blanco: $número_líneas_en_blanco";
  20.  
  21. __END__
  22. Número de líneas en blanco: 2
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Para el caso de las 'a' y 'b', hay que contemplar el caso de que la secuencia empiece por cualquiera de ellas. Y solo nos interesa el caso de que haya más de una. Un posible patrón sería parecido al anterior, pero podemos abreviarlo así: /a{2,}|b{2,}/, que quiere decir que buscamos por dos o más letras 'a' o dos más letras 'b'.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Modern::Perl '2012';        # Somos modernos
  3. use utf8::all;                  # Turn on UTF-8. All of it.
  4.  
  5. my $pruebas = <<EOF;
  6. aababaabb
  7. aaaab
  8.  
  9. ababbabbababbbbbbababbabba
  10.  
  11. aaaaaabbbbbb
  12. EOF
  13.  
  14. while ($pruebas =~ /(a{2,}|b{2,})/gsm) {
  15.     say "[$1]";
  16. }
  17.  
  18. __END__
  19. [aa]
  20. [aa]
  21. [bb]
  22. [aaaa]
  23. [bb]
  24. [bb]
  25. [bbbbbb]
  26. [bb]
  27. [bb]
  28. [aaaaaa]
  29. [bbbbbb]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ahora ya solo queda juntarlo todo :) /(a{2,}|b{2,}|\n\n+)/smg o así: /(a{2,}|b{2,}|\n{2,})/smg

Pero... dices que no quieres solo buscar, sino reemplazar, así que debemos empezar a pensar en usar el operador s///.
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

Re: Reconocer y contabilizar caracteres

Notapor koolik » 2012-04-22 14:22 @640

hola, gracias por tu ayuda explorer, de a poco voy entendiendo más.
Aplicando tu solución veo el siguienete problema, no detecta las líneas enteras.

Me explico:

Si viene una línea "aaabb", debe retornar a[3]b[2],con esta solución sólo detecta la que comienza en a, detecta sólo esa subtira.
Despliega "aa" y no "aabbb"

Tampoco contempla los patrones alternados: ababbaba
Cuyo resultado sería abab[2]aba.
O bien bbaba, que debería desplegar: b[2]aba

Si tengo la siguiente entrada:
aabbb => despliega aa
bba => despliega bb
ab => despliega fin de línea.
aba => sólo fin de línea

En base a tu ayuda intentaré modificar.

Saludos
koolik
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2012-04-21 17:42 @779

Re: Reconocer y contabilizar caracteres

Notapor explorer » 2012-04-22 14:34 @648

No, a ver: Yo no estoy dándote la solución final (ya la tengo hecha desde la primera hora en que pusiste el primer mensaje). Estoy intentando que averigües por ti mismo esa solución.

La expresión regular que te he dado sí que localiza lo que quieres buscar. Otra cosa es que necesitas modificar la cadena de partida.

Eso se puede hacer con una operación de sustitución s///, utilizando un patrón parecido a ese. De hecho, en mi solución separo por una parte la identificación de las líneas vacías de la parte de sustitución de la cadena, ya que así se ve y se entiende mucho mejor.

Inténtalo, y si no lo consigues encontrar, nos lo dices y ya te doy mi solución.

P.D. No todo tiene que ser regalado. Hay que luchar un poco más ;)
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

Re: Reconocer y contabilizar caracteres

Notapor koolik » 2012-04-22 15:57 @706

Pues me estoy acercando, pero me falta...
Esta es mi expresión:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while (<>)
  2. {              
  3.                
  4.         if (/((.*?)(((0{2,})(1{2,}))(.*?)|((1{2,})(0{2,}))(.*?)|(1{1,})|(0{1,}))(\n)|(\n\n+))/mg)
  5.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Después de chequear el if(), chequeo por el largo de los grupos $1, $2, y en función
de eso voy imprimiendo.

Me falta contemplar las expresiones del tipo aaabbaaa y aabbaabbbb. Tengo claro las expresiones regulares, pero no sé cómo capturar lo que debo imprimir.

(a{2,}b{2,})+ esto contempla aabbaabb, pero ¿cómo distingo que estoy en la segunda (o tercera) secuencias de 'a' y/o 'b'? Análogo para (b{2,}a{2,})+

(a{2,}b{2,})+(a{1,}) y análogo (b{2,}a{2,})+(b{2,})

y encima las del tipo aaaabababaaaaa

Me queda una expresión regular gigantesca, y por ende complicado de distinguir las subtiras que debo escribir.

Les agradezco cualquier sugerencia.
koolik
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2012-04-21 17:42 @779

Re: Reconocer y contabilizar caracteres

Notapor explorer » 2012-04-22 17:38 @776

No, no... te complicas mucho...

Hay un patrón en las expresiones regulares que sirve para referirse a lo que se acaba de capturar en el último grupo de captura.

Así, con /(a|b)\1+/ estamos diciendo: «busca por una 'a' o 'b', que esté seguida por una más veces de ella misma».

La marca \1 se refiere al primer grupo de paréntesis. Si los paréntesis han capturado una 'a', entonces es como si buscáramos /aa+/.

De esa forma, ya no necesitamos hacer distintas combinaciones de si 'a' va delante de 'b', o al revés.

Y para hacer la transformación, puedes usar la opción /e, que ejecuta un pequeño código Perl por cada coincidencia 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: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Reconocer y contabilizar caracteres

Notapor koolik » 2012-04-22 19:17 @845

Pues vaya, me he complicado y me cuesta entender.
/(a|b)\1+/ no hace lo que tu me dices, no sé si es por la versión y tal.

De hecho me reconoce sólo el primer carácter de cada línea.

Debí cambiarla por /(a|b)\+1/. De todos modos no captura todas las tiras que necesito, pero va mejor que la anterior.

Segundo, veré el patrón de cambio, necesito determinar la cantidad de 'a' y 'b'.
Saludos y gracias por tus aportes.
koolik
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2012-04-21 17:42 @779

Re: Reconocer y contabilizar caracteres

Notapor explorer » 2012-04-22 22:33 @981

Es que hay que hacer unos pequeños ajustes para quedarnos con toda la subtira:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my $pruebas = <<EOF;
  7. aababaabb
  8. aaaab
  9.  
  10. ababbabbababbbbbbababbabba
  11.  
  12. aaaaaabbbbbb
  13. EOF
  14.  
  15. while ($pruebas =~ /((a|b)\2+)/gsm) {
  16.     print "[$1]\n";
  17. }
  18.  
  19. __END__
  20. [aa]
  21. [aa]
  22. [bb]
  23. [aaaa]
  24. [bb]
  25. [bb]
  26. [bbbbbb]
  27. [bb]
  28. [bb]
  29. [aaaaaa]
  30. [bbbbbb]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Observa: el '\2' hace referencia al segundo par de paréntesis de captura, que es el que busca por una letra 'a' o 'b'. Entonces, lo que nos hace es buscar por secuencias de dos o más letras 'a' o 'b' repetidas. Y luego, el primer par de paréntesis captura todo. Y eso lo imprimimos como $1.

Para la segunda parte, puedes usar la opción /e, ya comentada...
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my $pruebas = <<EOF;
  7. aababaabb
  8. aaaab
  9.  
  10. ababbabbababbbbbbababbabba
  11.  
  12. aaaaaabbbbbb
  13. EOF
  14.  
  15. $pruebas =~ s/((a|b)\2+)/$2 . '[' . length($1) . ']'/ge;
  16.  
  17. print $pruebas;
  18.  
  19. __END__
  20. a[2]baba[2]b[2]
  21. a[4]b
  22.  
  23. abab[2]ab[2]abab[6]abab[2]ab[2]a
  24.  
  25. a[6]b[6]
  26.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Y ya va saliendo algo parecido a lo que queremos...
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

Siguiente

Volver a Básico

¿Quién está conectado?

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