• Publicidad

Diario de aprendizaje de un perlero desde cero

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

Notapor Zeokat » 2007-06-15 21:09 @923

Bueno con el siguiente código, puedo leer el número de palabras de la frase anteriormente escrita.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"frase.txt");

my $texto=<TEXTO>;

my @palabras = split(/\s/,$texto);

print "El numero de palabras de la frase es ", $#palabras + 1;

close (TEXTO);
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4



Ahora voy a ver si consigo hacer una solución más eficaz.... :)
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Publicidad

Notapor Zeokat » 2007-06-15 21:15 @927

Una aproximación a lo que creating decía supongo que es lo siguiente....


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"frase.txt");

my $texto=<TEXTO>;

my @palabras = split(/\w+/, $texto);

print "El numero de palabras de la frase es ", $#palabras + 1;

close (TEXTO);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4



En este caso la expresión regular no busca espacios, sino que divide por todo aquello que empieza por lo que no se considera carácter de palabra (es decir los símbolos).

Ahora toca tratar de hacerlo, pero no solo para una línea sino para varias y metiendo más de un espacio entre palabras, a ver qué sale.

:)
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Notapor Zeokat » 2007-06-15 21:45 @948

El siguiente código parece que no funciona... mmm... la función split parece que en los arrays funciona de otra manera...

Ahora lo que tengo es un texto.txt, el siguiente:

Código: Seleccionar todo
El avion vuela rapido y alto
El avion  vuela rapido y alto
  El avion vuela rapido  y alto
El avion         vuela rapido y alto


Y quiero saber el número de palabras que tiene.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"texto.txt");

my @texto=<TEXTO>;

my @palabras = split(/\w+/, @texto);

print $#palabras;

close (TEXTO);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pero no funciona... mmm... no sé cómo solucionarlo.

Help! Necesito una :idea: :wink:
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Notapor Zeokat » 2007-06-16 04:42 @237

Se me ocurrió hacer lo siguiente, pero tiene el inconveniente de que solo cuenta las palabras para un texto con unas determinadas líneas, en este caso para un texto de 4 líneas. La verdad es que no sé cómo hacer para que funcione tengas las líneas que tenga el archivo. :? :?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"texto.txt");

my @texto=<TEXTO>;

my $linea_0 = $texto[0];
my $linea_1 = $texto[1];
my $linea_2 = $texto[2];
my $linea_3 = $texto[3];

my @palabras_linea_0 = split(/\w+/, $linea_0);
my @palabras_linea_1 = split(/\w+/, $linea_1);
my @palabras_linea_2 = split(/\w+/, $linea_2);
my @palabras_linea_3 = split(/\w+/, $linea_3);

print "El numero de palabras del texto es ",$#palabras_linea_0 + $#palabras_linea_1 + $#palabras_linea_2 +

$#palabras_linea_3 + 1;

close (TEXTO);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Notapor explorer » 2007-06-16 06:49 @325

* Dividir la línea por la expresión regular \w+ quiere decir que tomará a las palabras como separadores y devolverá lo que no es palabra como elementos, y aquí hay que prestar mucha atención a lo que hacemos y cómo funciona todo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$x = "El avion vuela rapido y alto";
print scalar split /\w+/, $x;  # 6
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Vemos que sale 6, que parece que son el número de palabras de la línea y creemos que split ha contado las palabras. Pero veamos exactamente qué es lo que ha dividido split:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$x = "El avion vuela rapido y alto";
print '>' , join('.', split /\w+/, $x), '<'; # >. . . . . <
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Observemos:
  • hay 5 espacios, igual que en la frase que le hemos dado
  • pero el primer elemento está vacío (es un string vacío) (fijarse que está entre el '>' y el primer '.').
  • así que el número de elementos es 6.
Hemos llegado a contar 6 pero, ¿por qué?. Pues porque (primera frase en la documentación de split) se preservan los posibles campos vacíos que haya al principio y se desechan los del final. Los 'campos' aquí son las no-palabras. Como la frase empieza por una palabra eso quiere decir que delante de ella hay una no-palabra (de longitud 0, pero la hay). Le decimos a split que parte por las palabras, así que la no-palabra del principio es el primer elemento que nos devuelve.

Se verá más claro si la frase empieza por un espacio.

Así que hay que tener cuidado: hemos llegado a la solución, pero hay que entender cómo.

* Para el caso de que el texto tenga varias líneas, has optado primero por la opción de leerlo entero con @texto=<TEXTO>. Pero luego se lo pasas a split, y éste te devuelve un 0. ¿Por qué?. Una vez más conviene hacer un análisis minucioso de lo ocurrido:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
@palabras = split(/(\w+)/,@texto);  # Ponemos paréntesis porque queremos que nos devuelva también los delimitadores
print '>',join('.',@palabras),'<';  # >.4<
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Esto es lo que ocurre: @texto es tomado en contexto escalar, por lo que es un '4' (tiene cuatro elementos, por las cuatro líneas del texto). Y no es eso lo que queremos.

Una solución sería juntar las 4 líneas en una sola con un join('',@texto), y entonces split nos devolverá 25 (24 palabras que tiene el texto más la primera invisible).

Y la otra solución es procesar cada línea por separado, por ejemplo con un bucle foreach por @texto o un bucle while por <TEXTO> y llevar un contador de palabras encontradas en cada línea, para luego pintarlo al final.
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 Zeokat » 2007-06-16 08:37 @400

Excelente respuesta explorer. Tenía unos errores de concepto, ahora trataré de hacer unas pruebas a ver qué sale.

Aquí aprendí una cosa interesante y es una forma de pasar un array "@texto" a un escalar "$texto", que traté de hacerlo pero me complicaba con cosas raras cuando estaba ahí la función join.

El siguiente código pasa el array @texto a un escalar $texto

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"texto.txt");

my @texto=<TEXTO>;

my $texto = join('',@texto);

print $texto;

close (TEXTO);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Explicaré un poco que es lo que hace join en este caso. Pues coge todos los elementos del array @texto y los junta, usando como separador nada, de ahí que en la línea del join "my $texto = join('',@texto);" entre las comillas no se ponga nada quedando así... ('',@texto...

Si quisiera que me las juntara poniendo como separador un asterisco pondría ... ('*',@texto)...

Por cierto a ver si alguien me puede aclarar qué es lo que hace exactamente la función scalar. En la documentación pone:

Código: Seleccionar todo
"Forces EXPR to be interpreted in scalar context and returns the value of EXPR"
<------->Traducido<--------->
"Fuerza una expresión a ser interpretada en un contexto escalar y devuelve el valor de la expresión"


Parece que devuelve el número de elementos del array tal y como hacía $#nombre_del_array.

Lo que entendí del post que puso anteriormente creating021 es que el uso de scalar es más rápido, cómodo o más adecuado... o algo así... ¿estoy en lo cierto?

Este código seria una de las soluciones al problema de contar las palabras de un archivo.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"texto.txt");

my @texto=<TEXTO>;

my $texto = join('',@texto);  # Junto los elementos del array @texto y los almaceno en un escalar $texto

my @palabras = split(/\w+/, $texto);  # divido el escalar $texto usando como separadores las palabras
                                      # y las almaceno en el array @palabras

print scalar @palabras;  # Imprimo el número de elementos del escalar @palabras

close (TEXTO);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Notapor creating021 » 2007-06-16 08:45 @406

Bueno yo tengo una solución que con un poco de trabajo se puede usar como el comando de Unix wc.

Texto:
Código: Seleccionar todo
Un ejercicio muy facil,
   con buenos problemas que resolver,
      que me recuerda algunas cosas
   como las estructuras de HTML y XML
     pero bueno... eso sera despues.
Hmmm... ni modo, todo esto de puntos, comas y de mas me sacan.


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict;
use warnings;

open FL, "texto.txt" or die "Hmmm... que raro: $!\n";
my $count = 0;
while (my $linea = <FL>){
  my @palabras = split /\w+/, $linea;
  $count += $#palabras;
}
print "Pues resulta que el texto tiene $count palabras\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Si se le da soporte a codes, se puede trabajar con archivos muy grandes.
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

Notapor Zeokat » 2007-06-16 08:51 @410

No consigo ver muy bien cómo trabaja el split.

En el texto siguiente:

Código: Seleccionar todo
El avion vuela rapido y alto
El avion  vuela rapido y alto
  El avion vuela rapido  y alto
El avion         vuela rapido y alto


Podría asemejarlo a lo siguiente (sabiendo que el split en el ejercicio usa como separador las palabras, cambio cada palabra por un *)

Código: Seleccionar todo
* *  * * * *
  * * * *  * *
  * * * *  * *
* *         * * * *


El split usa como separador ahora el asterisco (suposición para simplificar), quedando como elementos el resto, sería algo así:


Código: Seleccionar todo
(e_vacio_0)*(e1)*(e2)*(e3)*(e4)*(e5)*


hay 6 elementos, eso en 4 líneas, da 24 elementos que es el número de no-palabras.

Código: Seleccionar todo
(e_vacio_0)*(e1)*(e2)*(e3)*(e4)*(e5)*
(e_vacio_0)*(e1)*(e2)*(e3)*(e4)*(e5)*
(e_vacio_0)*(e1)*(e2)*(e3)*(e4)*(e5)*
(e_vacio_0)*(e1)*(e2)*(e3)*(e4)*(e5)*


Me parece que sería algo así... como funciona. :roll:
Zeokat
Perlero nuevo
Perlero nuevo
 
Mensajes: 125
Registrado: 2006-08-22 08:08 @380

Notapor explorer » 2007-06-16 09:11 @424

Zeokat escribiste:Por cierto a ver si alguien me puede aclarar qué es lo que hace exactamente la función scalar. En la documentación pone:

Código: Seleccionar todo
"Forces EXPR to be interpreted in scalar context and returns the value of EXPR"
<------->Traducido<--------->
"Fuerza una expresión a ser interpretada en un contexto escalar y devuelve el valor de la expresión"

Perl tiene, básicamente, dos modos de trabajar, dos contextos: escalar y lista. Siempre, a la hora de programar, hay que tener en cuenta en qué contexto se están desarrollando las operaciones. Ver perlglossary, context.

Zeokat escribiste:Parece que devuelve el número de elementos del array tal y como hacía $#nombre_del_array.
Que no, que no lo has entendido. Que no es lo mismo el NÚMERO de elementos que el valor del ÍNDICE del ÚLTIMO elemento.

Zeokat escribiste:Lo que entendí del post que puso anteriormente creating021 es que el uso de scalar es más rápido, cómodo o más adecuado... o algo así... ¿estoy en lo cierto?
Es más claro, sí. Para comprobar si es más rápido habría que hacer un Benchmark. En situaciones normales no es necesario usarlo. Por ejemplo, cuando hacer alguna operación matemática, Perl pasa al contexto escalar el array por lo que siempre nos devuelve el número de sus elementos, y entonces no es necesario usar scalar.

Zeokat escribiste:Este código seria una de las soluciones al problema de contar las palabras de un archivo.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w

use strict;

open (TEXTO,"texto.txt");

my @texto=<TEXTO>;

my $texto = join('',@texto);  # Junto los elementos del array @texto y los almaceno en un escalar $texto

my @palabras = split(/\w+/, $texto);  # divido el escalar $texto usando como separadores las palabras
                                      # y las almaceno en el array @palabras

print scalar @palabras;  # Imprimo el número de elementos del escalar @palabras

close (TEXTO);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Sí, pero te da una palabra de más... la no-palabra del principio.
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 explorer » 2007-06-16 09:25 @434

Zeokat escribiste:No consigo ver muy bien cómo trabaja el split.
A ver... split divide cortando por los delimitadores. Si el delimitador es una palabra entonces nos devolverá lo que la palabra tenga a los lados, que serán los espacios en blanco (en este ejemplo concreto).

Pero con la salvedad de que si hay un delimitador al comienzo, split piensa que debería haber ahí un campo, pero falta, por lo que nos devuelve un valor vacío. Eso es lo que pasa en las líneas 1ª, 2ª y 4ª. En la tercera línea, sin embargo, sí que hay algo delante del separador 'El', por lo que nos devuelve ese campo (un par de espacios en blanco). El resultado neto es que siempre nos devuelve un campo más: el que está delante del primer delimitador (palabra) de cada línea.

Y este comportamiento no se reproduce en los finales de línea. Todas las líneas acaban en palabras (delmitadores) pero split no nos incluye un campo vacío extra.
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

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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

cron