Página 1 de 1

Aplicar split en array con ciertas condiciones

NotaPublicado: 2015-10-24 03:58 @207
por sisifo80
Hola.

Tengo una entrada con el siguiente formato:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
texto
texto
...
(ID 3467)

texto
texto
...
(ID 3467)

texto
texto
...
(ID 5993)
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Es decir: Tengo un conjunto variable de líneas de texto cuya última línea es un código entre paréntesis, y después otro conjunto variable de líneas de texto cuya última línea es un código -y aquí viene mi complicación- que puede ser o no el mismo código que el anterior, y así sucesivamente...

Necesito un script que lea ese archivo y cree tantas carpetas como códigos diferentes existan (el nombre de cada carpeta será el propio código), y que dentro de cada carpeta cree un archivo (el nombre del archivo será también el propio código) en cuyo contenido se imprima la parte de texto de la entrada que corresponda a ese código.

Por ejemplo, siguiendo con el ejemplo anterior, debería obtener lo siguiente:

a) una carpeta llamada "3467" que contenga un archivo llamado "3467" cuyo contenido sea:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
texto
texto
...
ID 3467

texto
texto
...
ID 3467
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


b) una carpeta llamada "5993" que contenga un archivo llamado "5993" cuyo contenido sea:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
texto
texto
...
ID 5993
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Y así, sucesivamente.

Pues bien, yo llego hasta aquí:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $filename = shift;
  2. open F, $filename or die;
  3. undef $/;
  4. $file = <F>;
  5. close F;
  6.  
  7. @s = split /\(ID .*?\K\n/, $file;              # divido la entrada en partes siempre que encuentre la secuencia ID + cualquier cosa + cambio de línea
  8.  
  9. foreach $s (@s) {
  10.  
  11.     if ( $s =~ m/\ID (.*?)\)/ ) {              # capturo el código en una variable
  12.         $code = $1;
  13.     }
  14.  
  15.     mkdir "$code";                             # creo carpeta con el código
  16.                                                # creo archivo con el código
  17.     open FILE, '>', "$code/$code\.txt" || die "can't open file output/$code";
  18.     print FILE "$s";
  19.     close FILE;
  20.  
  21. }
  22.  
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4


Como veis, solo sé dividir la entrada en partes siendo cada parte un conjunto del tipo "texto, texto, text, ID código". Pero lo que quisiera, y no sé cómo, es que mi array tuviese en cuenta que si el código es igual al anterior no aplique la función split(), para dividir así el texto en las partes que realmente necesito.

No sé si me he explicado muy bien...

Re: Aplicar split en array con ciertas condiciones

NotaPublicado: 2015-10-24 04:11 @216
por explorer
Hay otra opción, muy buena: en lugar de dividir por el ID, hacerlo por la línea en blanco que le sigue.

Re: Aplicar split en array con ciertas condiciones

NotaPublicado: 2015-10-24 05:06 @254
por sisifo80
Hola, explorer. Gracias por tu respuesta.

El problema es que la línea en blanco no es sistemática: podría aparecer o no. Lo único sistemático es la línea con el código después de cada conjunto de texto. Por otro lado, y suponiendo que la línea en blanco sí fuese sistemática, no entiendo cómo podría eso resolver mi problema, pues seguiría obteniendo divisiones inferiores a lo que yo necesito (a veces necesitaría que varias líneas en blanco se capturasen en la misma subdivisión y a veces no, puesto que el código que sigue a cada conjunto de texto a veces es igual al anterior y a veces no).

Re: Aplicar split en array con ciertas condiciones

NotaPublicado: 2015-10-25 10:02 @459
por explorer
Esta es una posible solución, aunque no acabo de entender el porqué hay que crear un subdirectorio con el nombre del ID, ya que solo con crear el archivo de basado en el ID, vale.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.18;
  3. use autodie;
  4. use File::Slurp;
  5.  
  6. my $archivo = read_file('code_39015.txt');
  7.  
  8. my %ids;                                        # base de datos
  9.  
  10. while ($archivo =~ /\G\s*(?<texto>.+?)\s*\(ID (?<id>\d+)\)/msg) {
  11.  
  12.     my($texto, $id) = @+{qw'texto id'};
  13.  
  14.     push @{ $ids{ $id } }, $texto;
  15. }
  16.  
  17. for my $id (keys %ids) {
  18.  
  19.     mkdir $id;
  20.    
  21.     write_file("$id/$id.txt", join("\n" => @{ $ids{$id} }) . "\nID $id\n");
  22. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Lo que hacemos es ir guardando en un hash de array todas las partes que siguen el patrón buscado.

Luego, solo queda recuperar los ID y generar la salida.

Re: Aplicar split en array con ciertas condiciones

NotaPublicado: 2015-10-27 02:44 @156
por sisifo80
Muchas gracias, explorer.