Lun Dic 11, 2006 12:53 pm
|
 |
nany
Perlero Nuevo

|
Registrado: 11 Dic 2006
Mensajes: 17
|
|
| Dividir un archivo por líneas |
|
|
Hola
Ojalá puedan ayudarme.
Tenga una lista de archivos en un directorio y ya los leí uno por uno. ¿Cómo puedo hacer para que en caso de que pase de las tres mil líneas cree el archivo con tres mil y después cree el mismo archivo añadiendo el numero dos y con las líneas restantes? ¡¡¡¡¡¡¡Ayúdenme!!!!!!! |
|
|
|
Lun Dic 11, 2006 3:04 pm
|
 |
monoswim
Vive para Perl en Español

|
Registrado: 18 Nov 2003
Mensajes: 720
Ubicación: Buenos Aires
|
|
|
|
|
No te entendí mucho , pero es fácil...
¿ Sabés leer un archivo línea por línea ?
| Perl: | open(FILE, '<fff.txt');
while(my $line = <FILE>){
}
close FILE;
#PARA CONTAR LAS LÍNEAS SIMPLEMENTE $i++;
|
¿ Sabés crear un nuevo archivo ? open(FILE,'>NEWFILE')
No creo que tengas mayores complicaciones... Hacer un condicional que evalúe el $i y ya...
Espero que te sirva
saludos |
|

Lun Dic 11, 2006 5:01 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4225
Ubicación: Valladolid, España
|
|
|
|
|
Supongamos que has metido todas las líneas en el array @lineas.
Si suponemos también que el fichero puede tener entre 1 y 6000 líneas, tenemos que dividir su contenido entre uno o dos ficheros.
| Perl: | $fichero = "salida1";
@resto = splice( @lineas, 3_ 000 );
print "Salida en fichero 1 $fichero\n";
# Aquí grabamos las @lineas
++ $fichero;
if ( @resto ) {
print "Salida en fichero 2 $fichero\n";
# Aquí grabamos el @resto
} |
Darse cuenta de que ni siquiera comprobamos si tenemos 3000 líneas, más o menos... Perl nos ahorra MUCHO trabajo. |
|
Mar Dic 12, 2006 1:55 pm
|
 |
creating021
Vive para Perl en Español

|
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
|
|
|
|
Lun Dic 18, 2006 1:34 pm
|
 |
nany
Perlero Nuevo

|
Registrado: 11 Dic 2006
Mensajes: 17
|
|
| respuestas |
|
|
hola, mil gracias por sus respuestas; me fueron muy útiles. ¡¡¡¡saludos!!!!  |
|

Lun Dic 18, 2006 1:43 pm
|
 |
nany
Perlero Nuevo

|
Registrado: 11 Dic 2006
Mensajes: 17
|
|
|
|
|
Hola, podrían ayudarme por favor a revisar este código, ¡¡¡¡please!!!!
| Perl: | ################///Abrir Directorio
opendir DIR, "$s_Dir" or die "ERR: Al leer directorio [ " . $s_Dir . "]\n";
my @a_Archivos = readdir (DIR );
close DIR;
###############///Abrir Archivo
sub leeArchivoArr {
foreach my $s_NombreArchivo (@a_Archivos){
my $s_Archivo = $s_Dir . "/" . $s_NombreArchivo;
open IN, "$s_Archivo" or die "ERR: Al abrir [ $s_Archivo ]\n";
my $i_ContLineas = 0;
while (<IN>) {
$i_ContLineas++;
}
print "INF: Archivo [$s_Archivo] con [$i_ContLineas ] Lineas\n";
close IN;
###############///comparacion
while (scalar @a_Archivo > 3000){
my @a_arreglo3000 = splice @a_Archivo, 3000;
my $s_archivonuevo = "$home" + "$s_archivonuevo" + "$i_Contarchivo";
open OUT , ">$s_archivonuevo";
print OUT "$s_arreglo3000\n";
close OUT;
my $s_contArchivo = 0;
$s_contArchivo ++;
}
if ($a_Archivo < 3000){
my $s_archivonuevo = "$home" + "$s_archivonuevo" + "$i_Contarchivo";
open OUT , ">$s_archivonuevo";
print OUT "$a_Archivo";
close OUT;
}
} |
|
|

Lun Dic 18, 2006 4:18 pm
|
 |
creating021
Vive para Perl en Español

|
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
|
|
|
|
|
| Perl: | #!/usr/bin/env perl
use strict;
use Cwd;
my $s_Dir = getcwd ();
opendir DIR, "$s_Dir" or die "ERR: Al leer directorio [ " . $s_Dir . "]\n";
my @a_Archivos = readdir (DIR );
closedir DIR;
sub leerArchivoArr {
foreach my $file (@a_Archivos){
if(-f $file){ # si es un fichero...
open IN, $file or die "Error: $_ $!\n";
my $linea = 0;
while(<IN>){
$linea++;
}
close IN;
print "INF: Archivo [$s_Dir/$file] con [$linea] Lineas\n";
}
}
}
leerArchivoArr (); |
Lo otro no se para que así que... |
|

Lun Dic 18, 2006 5:08 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4225
Ubicación: Valladolid, España
|
|
|
|
|
Hay varios errores:
* La variable $s_arreglo3000 no está inicializada en ningún sitio. Supongo que te refieres a la @a_arreglo3000.
* La línea de 'my $s_contArchivo = 0;' debería estar antes del while. De otra forma, ese contador siempre valdrá uno dentro del bucle e indefinido fuera de él.
* La variable $a_Archivo no está inicializada en ningún sitio. Supongo que te refieres a la @a_Archivo.
* ¿Qué ocurre si el número de líneas es exactamente múltiplo de 3000? Pues que el último if también se ejecuta y se crea un archivo nuevo de tamaño 0. |
|
Lun Dic 18, 2006 5:39 pm
|
 |
creating021
Vive para Perl en Español

|
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
|
|
|
|
Lun Dic 18, 2006 5:45 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4225
Ubicación: Valladolid, España
|
|
|
|
|
| La coma no sirve para concatenar strings. |
|
Lun Dic 18, 2006 6:07 pm
|
 |
creating021
Vive para Perl en Español

|
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
|
|
|
|
|
| explorer escribió: | | La coma no sirve para concatenar strings. |
cierto, que pena de verdad, no sirve. |
|
Mar Dic 19, 2006 10:51 am
|
 |
nany
Perlero Nuevo

|
Registrado: 11 Dic 2006
Mensajes: 17
|
|
|
|
|
| gracias por sus respuestas la verdad me ha costado un poco de trabajo este lenguaje saludos!!!!! |
|

Mar Dic 19, 2006 11:20 am
|
 |
Perl user
Maestro Honorario

|
Registrado: 03 Nov 2004
Mensajes: 385
|
|
|
|
|
| explorer escribió: | Supongamos que has metido todas las líneas en el array @lineas.
Si suponemos también que el fichero puede tener entre 1 y 6000 líneas, tenemos que dividir su contenido entre uno o dos ficheros.
| Perl: | $fichero = "salida1";
@resto = splice( @lineas, 3_ 000 );
print "Salida en fichero 1 $fichero\n";
# Aquí grabamos las @lineas
++ $fichero;
if ( @resto ) {
print "Salida en fichero 2 $fichero\n";
# Aquí grabamos el @resto
} |
Darse cuenta de que ni siquiera comprobamos si tenemos 3000 líneas, más o menos... Perl nos ahorra MUCHO trabajo. |
No reinventemos el hilo negro, ya está hecho.
Tie::File hace estas tareas demasiado sencillas y triviales, como para evitarnos el uso de splice y lectura directa. Recordemos que Tie::File incluso tiene caching y otras monerías muy útiles.
Échenle un vistazo al módulo, no por algo está dentro de los Core modules de Perl.
Saludos. |
|

Mar Dic 19, 2006 2:11 pm
|
 |
nany
Perlero Nuevo

|
Registrado: 11 Dic 2006
Mensajes: 17
|
|
|
|
|
Hola a todos. Bueno, el leer línea por línea ya me queda claro pero aún no he podido generar que de un archivo de supongamos 8500 líneas que se llama juanito me derive tres archivos uno con juanito1 con las primeras 3000 líneas, juanito2 con las siguientes 3000 líneas y juanito3 con las restantes. Este es mi código que aunque según ya no tiene errores no hace lo que pido. Ayuda.
| Perl: | /Abrir Directorio
opendir DIR, "$s_Dir" or die "ERR: Al leer directorio [ " . $s_Dir . "]\n";
my @a_Archivos = readdir (DIR );
close DIR;
###############///Abrir Archivo
sub leeArchivoArr {
foreach my $s_NombreArchivo (@a_Archivos){
my $s_Archivo = $s_Dir . "/" . $s_NombreArchivo;
open IN, "$s_Archivo" or die "ERR: Al abrir [ $s_Archivo ]\n";
my $i_ContLineas = 0;
my @a_Archivo = <IN>;
print "INF: Archivo [$s_Archivo] con [$i_ContLineas ] Lineas\n";
close IN;
###############///comparacion
my $s_contArchivo1 = 0;
while (scalar @a_Archivo > 3000){
my @a_arreglo3000 = splice (@a_Archivo, 3000);
my $s_archivonuevo = $ENV{"HOME"}. "$s_NombreArchivo". "$s_contArchivo1";
open OUT , ">$s_archivonuevo";
print OUT "$s_Archivo\n";
close OUT;
$s_contArchivo1 ++;
}
if (@a_Archivo < 3000){
my $s_contArchivo = 0;
my $s_archivonuevo = $ENV{"HOME"}. "$s_NombreArchivo" . "$s_contArchivo";
open OUT , ">$s_archivonuevo";
print OUT "$s_Archivo";
close OUT;
$s_contArchivo ++;
}
} |
|
|

Mar Dic 19, 2006 8:40 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4225
Ubicación: Valladolid, España
|
|
|
|
|
Hay algunos errores de lógica. Hay algunas variables que nunca se usan o nunca han sido inicializadas.
Lo primero que he hecho es crear unos ficheros de prueba con el comando
| bash: | perl -le 'print "Linea ", ++$numero for 1..8500' > juanito |
El siguiente programa busca en el subdirectorio 'ficheros' todos esos ficheros generados antes y los divide, dejándolos en el directorio raíz, como pones en tu programa.
| Perl: | 1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 my $s_Dir = 'ficheros';
7
8 ### Abrir Directorio
9 opendir DIR, "$s_Dir" or die "ERR: Al leer directorio [ $s_Dir ]\n";
10 my @a_Archivos = grep { -f "$s_Dir/$_" } readdir (DIR );
11 close DIR;
12
13 ### Abrir Archivo
14 foreach my $s_NombreArchivo ( @a_Archivos ) {
15 my $s_Archivo = $s_Dir . "/" . $s_NombreArchivo;
16 open IN, "$s_Archivo" or die "ERR: Al abrir [ $s_Archivo ]\n";
17 my @a_Archivo = <IN>;
18 print "INF: Archivo [$s_Archivo] con [", scalar @a_Archivo, "] Lineas\n";
19 close IN;
20
21 ### Comparación
22 my $s_contArchivo1 = 1;
23 while ( @a_Archivo > 3000 ) {
24 my @a_arreglo3000 = splice(@a_Archivo, 0, 3000);
25 my $s_archivonuevo = $ENV{"HOME"}. "/$s_NombreArchivo$s_contArchivo1";
26
27 print "INF: Archivo salida [$s_archivonuevo]\n";
28 open OUT , ">$s_archivonuevo";;
29 print OUT @a_arreglo3000;
30 close OUT;
31 $s_contArchivo1++;
32 }
33
34 if (@a_Archivo <= 3000) {
35 my $s_archivonuevo = $ENV{"HOME"}. "/$s_NombreArchivo$s_contArchivo1";
36
37 print "INF: Archivo salida [$s_archivonuevo]\n";
38 open OUT , ">$s_archivonuevo";
39 print OUT @a_Archivo;
40 close OUT;
41 $s_contArchivo1++;
42 }
43 } | * En las líneas 3 y 4 activamos unos pragmas para que nos ayuden a programar bien
* En la décima vamos leyendo todos los ficheros del directorio, pero sólo nos quedamos con aquellos que sean realmente ficheros normales (-f)
* El bucle de la decimo cuarta y siguientes analiza todos esos ficheros. Por cada uno lo abrimos y lo leemos entero
* Luego comienza la división. Con el bucle while repetimos mientras tengamos más de tres mil líneas
* En la línea vigésimo cuarta obtenemos las primeras tres mil líneas
* Y las grabamos en la vigésimo novena
* En la trigésimo primera, incrementamos el contador sufijo del nombre de salida
* El if de las líneas trigésimo cuarta y siguientes hacen lo mismo con el resto del fichero. Realmente no es necesario este if porque sabemos que ahí el fichero siempre tiene menos de tres mil líneas
Una mejora en la lógica sería: vamos a partir un fichero mientras tengamos algo que partir:
| Perl: | 1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 my $s_Dir = 'ficheros';
7
8 # Abrir Directorio
9 opendir DIR, "$s_Dir" or die "ERR: Al leer directorio [ $s_Dir ]\n";
10 my @a_Archivos = grep { -f "$s_Dir/$_" } readdir (DIR );
11 close DIR;
12
13 ### Abrir Archivo
14 foreach my $s_NombreArchivo ( @a_Archivos ) {
15 my $s_Archivo = $s_Dir . "/" . $s_NombreArchivo;
16 open IN, "$s_Archivo" or die "ERR: Al abrir [ $s_Archivo ]\n";
17 my @a_Archivo = <IN>;
18 print "INF: Archivo [$s_Archivo] con [", scalar @a_Archivo, "] Lineas\n";
19 close IN;
20
21 ### Comparación
22 my $s_contador = 1;
23 while ( @a_Archivo ) {
24 my @a_arreglo3000 = splice(@a_Archivo, 0, 3000);
25 my $s_salida = "$ENV{HOME}/$s_NombreArchivo$s_contador";
26 print "INF: Archivo salida [$s_salida]\n";
27 open OUT , ">$s_salida";
28 print OUT @a_arreglo3000;
29 close OUT;
30 $s_contador++;
31 }
32 } | Los únicos cambios están en la parte de Comparación:
* En la línea 22 tenemos una variable contador que se encargará del sufijo
* La línea siguiente es la base de la lógica: mientras tengamos líneas qué repartir...
* ... sacamos 3000 de ellas con splice en la línea siguiente
* Las imprimimos, y listo.
Claro que... si estuvieras en Unix, este problema lo tendrías resuelto con el comando 'split':
| bash: | split -l 3000 -a 1 -d juanito juanito |
|
|

Powered by phpBB © 2001, 2005 phpBB Group
|