• Publicidad

Omitir texto entre dos bloques

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

Omitir texto entre dos bloques

Notapor Leo_Gutierrez » 2009-08-07 13:25 @600

Hola a todos.

Tengo un archivo de texto, llamese "file.txt", con el siguiente contenido:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 1234# 
  2. blablabalbalb 
  3. blablablabl 
  4. balblabl 
  5. 456546# 
  6. blablabalbalb 
  7. blablablabl 
  8. balblabl 
  9. 45646# 
  10. blablabalbalb 
  11. blablablabl 
  12. balblabl 
  13. 46456# 
  14. blablabalbalb 
  15. blablablabl 
  16. balblabl 
  17.  

¿Como puedo borrar la línea desde el numero hasta el segundo delimitador '#'?, por ejemplo, borrar esto.

Sintáxis: [ Descargar ] [ Ocultar ]
  1. 45646# 
  2. blablabalbalb 
  3. blablablabl 
  4. balblabl 


He intentado resolverlo por medio de archivo por lotes .bat, pero no he tenido exito, ya que se me dificulta con el caracter '#', ya que hay varios.

Quisiera que me brindaran un trozo de código o me dieran los pasos indicados para realizarlo.
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Publicidad

Re: Omitir texto entre dos bloques.

Notapor netsoul » 2009-08-08 02:54 @162

Disculpa, no entendí tu pregunta. ¿Podrías colocar un código que hayas intentado?
With Perl
Imagination is more important than knowledge. Albert Einstein.
netsoul
Perlero nuevo
Perlero nuevo
 
Mensajes: 150
Registrado: 2008-05-04 01:11 @091

Re: Omitir texto entre dos bloques.

Notapor Leo_Gutierrez » 2009-08-08 13:12 @591

Hola, aquí el problema es que no lo he hecho en Perl, no he podido hacerlo con el, con otro lenguaje ya pude, con Batch.

Mira, tengo el siguiente archivo de texto, file.txt:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 1234# 
  2. blablabalbalb 
  3. blablablabl 
  4. balblabl 
  5. 456546# 
  6. blablabalbalb 
  7. blablablabl 
  8. balblabl 
  9. 45646# 
  10. blablabalbalb 
  11. blablablabl 
  12. balblabl 
  13. 46456# 
  14. blablabalbalb 
  15. blablablabl 
  16. balblabl 

Quiero editar el archivo de texto, omitiendo esta parte:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 45646# 
  2. blablabalbalb 
  3. blablablabl 
  4. balblabl 

Y que lo muestre así:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 1234# 
  2. blablabalbalb 
  3. blablablabl 
  4. balblabl 
  5. 456546# 
  6. blablabalbalb 
  7. blablablabl 
  8. balblabl 
  9. 46456# 
  10. blablabalbalb 
  11. blablablabl 
  12. balblabl 

Saludos.
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Omitir texto entre dos bloques

Notapor explorer » 2009-08-08 21:16 @928

¿Y dónde está el código en batch?
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Omitir texto entre dos bloques

Notapor Leo_Gutierrez » 2009-08-09 01:59 @124

Aquí está, explorer.

Sintáxis: [ Descargar ] [ Ocultar ]
  1. @echo off 
  2. setlocal enabledelayedexpansion 
  3. for /f "tokens=1 delims=[]" %%_ in ('type "file.txt" ^| find /i /n "45646#"') do set "coincidencia=%%_" 
  4. if not defined coincidencia ( 
  5. echo.No se encontró ninguna coincidencia "45646#" 
  6. goto:eof 
  7. :: Meter líneas de archivo. 
  8. set /a "contador=0" 
  9. for /f "eol= tokens=* delims=" %%x in (file.txt) do ( 
  10. set /a "contador+=1" 
  11. set linea!contador!=%%x 
  12. for /l %%: in (%coincidencia%, 1, %contador%) do ( 
  13. if "!linea%%:!"=="#" ( 
  14. set /a "coincidencia_final=%%:" 
  15. goto:break 
  16. :break 
  17. if not defined coincidencia_final ( 
  18. echo.No se encontró ninguna coincidencia 
  19. goto:eof 
  20. echo.Archivo normal: 
  21. for /l %%: in (1,1, %contador%) do (echo %%: : !linea%%:!) 
  22. echo. 
  23. echo. 
  24. echo.Archivo modificado: 
  25. for /l %%: in (1,1, %contador%) do ( 
  26. if %%: lss %coincidencia% (echo %%: : !linea%%:!) 
  27. if %%: gtr %coincidencia_final% (echo %%: !linea%%:!) 
  28. pause>nul 
  29. exit /b 0 


Esta es la salida que me da:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. C:\>code.bat 
  2. Archivo normal: 
  3. 1 : 1234# 
  4. 2 : blablabalbalb 
  5. 3 : blablablabl 
  6. 4 : balblabl 
  7. 5 : # 
  8. 6 : 456546# 
  9. 7 : blablabalbalb 
  10. 8 : blablablabl 
  11. 9 : balblabl 
  12. 10 : # 
  13. 11 : 45646# 
  14. 12 : blablabalbalb 
  15. 13 : blablablabl 
  16. 14 : balblabl 
  17. 15 : # 
  18. 16 : 46456# 
  19. 17 : blablabalbalb 
  20. 18 : blablablabl 
  21. 19 : balblabl 
  22. 20 : # 
  23.  
  24.  
  25. Archivo modificado: 
  26. 1 : 1234# 
  27. 2 : blablabalbalb 
  28. 3 : blablablabl 
  29. 4 : balblabl 
  30. 5 : # 
  31. 6 : 456546# 
  32. 7 : blablabalbalb 
  33. 8 : blablablabl 
  34. 9 : balblabl 
  35. 10 : # 
  36. 16 46456# 
  37. 17 blablabalbalb 
  38. 18 blablablabl 
  39. 19 balblabl 
  40. 20 # 
  41.  
  42. C:\> 


Quiero hacerlo en Perl para ir aprendiendo y no recurrir a scripts batch.

Por cierto, acabo de comprar el libro : "Perl, Manual de Referencia", de Martin C. Brown, estoy contento :D
Saludos.
Última edición por explorer el 2009-08-09 08:05 @378, editado 1 vez en total
Razón: Ortografía
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Omitir texto entre dos bloques

Notapor netsoul » 2009-08-09 04:17 @220

Creo que ya lo entendí. :D
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. $/ = '';
  6.  
  7. while(<>) {
  8.         s/45646#.*?#\n//s;
  9.         print;
  10. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Para ejecutarlo, puedes hacerlo de la siguiente manera:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
netsoul@intel:~$ perl script.pl file.txt > file_modificado.txt
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Si no quieres usar un script, puedes recurrir a perlrun:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
netsoul@intel:~$ perl -00pe 's/45646#.*?#\n//s' file.txt > file_modificado.txt
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Espero que esta vez, no se me haya escapado nada... jeje
With Perl
Imagination is more important than knowledge. Albert Einstein.
netsoul
Perlero nuevo
Perlero nuevo
 
Mensajes: 150
Registrado: 2008-05-04 01:11 @091

Re: Omitir texto entre dos bloques

Notapor Leo_Gutierrez » 2009-08-09 13:04 @586

Funciona bien el script, gracias.

explorer, ¿a qué te refieres con "ortografía"?
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Omitir texto entre dos bloques

Notapor explorer » 2009-08-09 13:10 @590

Bueno, netsoul te ha dado unas buenas respuestas, pero creo que exceden un poco el nivel del foro Básico.

Yo te daré algunas soluciones más sencillas, y espero que fáciles de entender.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. open my $fichero, q[<], 'code_18298.txt' or die;      # Abrimos el $fichero de entrada
  3. open my $salida,  q[>], 'salida_198.txt' or die;      # Abrimos el fichero de $salida
  4.  
  5. my $bloque_a_eliminar = 0;
  6.  
  7. while (my $linea = <$fichero>) {                      # Para cada la $línea del $fichero
  8.  
  9.     if ($linea =~ m/^45646\#/) {                      # Si detectamos comienzo del bloque
  10.         $bloque_a_eliminar = 1;                       # Indicamos que estamos dentro del $bloque_a_eliminar
  11.         next;                                         # Y saltamos a la siguiente línea
  12.     }
  13.  
  14.     if ($linea =~ m/^\#/ and $bloque_a_eliminar) {    # Si estamos en el $bloque_a_eliminar y llegamos a su final
  15.         $bloque_a_eliminar = 0;                       # Ya estamos fuera del bloque
  16.         next;                                         # Y saltamos a la siguiente línea
  17.     }
  18.  
  19.     if ($bloque_a_eliminar) {                         # Si estamos en el $bloque_a_eliminar
  20.         next;                                         # Saltamos a la siguiente línea
  21.     }
  22.  
  23.     print $salida $linea;                             # Si no es nada de lo anterior, sacamos la $línea a la $salida
  24. }
  25.  
  26. close $fichero;                                       # Cerramos ficheros
  27. close $salida;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Vemos el resultado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
explorer@portatil:~/Documents/Desarrollo> diff -y code_18298.txt salida_198.txt
1234#                                                           1234#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
456546#                                                         456546#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
45646#                                                        <
blablabalbalb                                                 <
blablablabl                                                   <
balblabl                                                      <
#                                                             <
46456#                                                          46456#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Efectivamente, el bloque ya no está.

Otra solución muy buena es usar los flip-flop:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. open my $fichero, q[<], 'code_18298.txt' or die;
  3. open my $salida,  q[>], 'salida_198.txt' or die;
  4.  
  5. while (my $linea = <$fichero>) {
  6.  
  7.     if ($linea =~ /^45646\#/ .. $linea =~ /^\#/) {
  8.         next;
  9.     }
  10.  
  11.     print $salida $linea;
  12. }
  13.  
  14. close $fichero;
  15. close $salida;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que, de forma abreviada, queda
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. open my $fichero, q[<], 'code_18298.txt' or die;
  3. open my $salida,  q[>], 'salida_198.txt' or die;
  4.  
  5. while (<$fichero>) {
  6.  
  7.     next if /^45646\#/ .. /^\#/;
  8.  
  9.     print $salida $_;
  10. }
  11.  
  12. close $fichero;
  13. close $salida;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El funcionamiento de los flip-flop es: comprobar la primera expresión; si es cierta, el operador '..' devuelve cierto en las siguientes comprobaciones, hasta que se cumpla la siguiente condición, que hace devolver falso a partir de ese momento.

En este caso, la primera condición es la primera línea que queremos quitar, y la segunda condición, la última línea. Mientras el operador flip-flop devuelva verdadero (estamos en el bloque a extraer), haremos un 'next' para no imprimir esa línea y saltar a procesar la siguiente línea.

Se puede incluso hasta simplificar todo el bucle while() en:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     print $salida $_ if ! (/^45646\#/ .. /^\#/);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Es decir: imprimimos solo aquellas líneas que no (!) están dentro del bloque a extraer.

Ahora bien, todo esto lo estamos haciendo con un fichero de entrada y sacando el resultado a otro fichero de salida.

Como el fichero parece pequeño, podemos leerlo en memoria, hacer la extracción, y guardar el resultado en el mismo fichero:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. open my $fichero, q[<], 'code_18298.txt' or die;
  3. my @fichero = <$fichero>;
  4. close $fichero;
  5.  
  6. open my $salida,  q[>], 'code_18298.txt' or die;
  7. for (@fichero) {
  8.     print $salida $_ if ! (/^45646\#/ .. /^\#/);
  9. }
  10. close $salida;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Otra forma de escribir el bucle for() sería:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for my $linea (grep { ! (/^45646\#/ .. /^\#/) } @fichero ) {
    print $salida $linea;
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Aún más abreviado sería usar las facilidades de edición de Perl, permitiendo editar el fichero desde la propia línea de comandos, como te ha mostrado netsoul, pero esta vez indicando que deseas cambiar el propio fichero de entrada.

Primero hacemos una prueba para comprobar si es correcto lo que queremos hacer:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
explorer@portatil:~/Documents/Desarrollo> perl -n -e 'print if ! (/^45646\#/ .. /^\#/)' code_18298.txt
1234#
blablabalbalb
blablablabl
balblabl
#
456546#
blablabalbalb
blablablabl
balblabl
#
46456#
blablabalbalb
blablablabl
balblabl
#
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Con la ayuda de '-n' recorremos todo el fichero, al que aplicamos a cada línea el código Perl indicado por '-e', que dice que imprima la línea si no pertenece al bloque a extraer.

Como vemos que funciona, ya solo queda aplicar el operador '-i', que realiza la edición del propio fichero de entrada:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
explorer@portatil:~/Documents/Desarrollo> perl -n -i -e 'print if ! (/^45646\#/ .. /^\#/)' code_18298.txt
explorer@portatil:~/Documents/Desarrollo> diff -y code_18298.txt code_18298.txt.bak
1234#                                                           1234#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
456546#                                                         456546#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
                                                              > 45646#
                                                              > blablabalbalb
                                                              > blablablabl
                                                              > balblabl
                                                              > #
46456#                                                          46456#
blablabalbalb                                                   blablabalbalb
blablablabl                                                     blablablabl
balblabl                                                        balblabl
#                                                               #
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: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Omitir texto entre dos bloques

Notapor Leo_Gutierrez » 2009-08-09 17:09 @756

Oh, me han encantado las soluciones, en especial la de "flip-flop".

Sólo una última pregunta.

¿Qué diferencia hay entre usar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. open(my $ARCHIVO, "<file.txt")
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. open(my $ARCHIVO, q[<], 'file.txt')
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

?
Me refiero al uso de "q[<]".

Una última recomendación.

Estoy en Ubuntu, uso gedit para los script en Perl; es bueno su coloreado, pero no posee sangrado.

¿Qué otro programa podría usar para esa cuestión?
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Omitir texto entre dos bloques

Notapor explorer » 2009-08-09 20:04 @878

No hay diferencia. La función open() permite usar de cero a tres argumentos.

En cuanto a editores de texto, hay muchos.

En estos foros, hay varias discusiones sobre el tema. Usa el sistema de búsqueda.

Yo, particularmente, uso joe, Kate, y Eclipse+e-p-i-c, según el tamaño del proyecto.

En los últimos tiempos, se ha puesto de moda el editor Padre, aunque a veces es complicado de instalar.

En la YAPC::EU::2009 pude ver que casi todo el mundo usaba Vim, seguidos de cerca por los usuarios de Emacs.
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: Bing [Bot] y 15 invitados

cron