• Publicidad

Capturar doble salto línea con expresión regular

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

Capturar doble salto línea con expresión regular

Notapor Alfumao » 2023-07-17 03:52 @203

Buenos días a todos (y en especial a explorer).

Tengo un problema para capturar unos valores con una expresión regular que tiene como base la aparición de dos saltos de línea consecutivos.

He de capturar 2 valores de una tabla incluida en un archivo con formato .txt y la única forma de hacerlo es, primero detectar un doble salto de línea y después capturar los valores, ya que la tabla no tiene un número de líneas fijo, y los valores que necesito se encuentran en la última línea.

Os dejo a continuación la expresión regular (que generé y no me está funcionando) y un ejemplo de la tabla a la que me refiero.

$_=~/([\d+\,]+)\s+([\d+\,]+\.\d+)\r\n\r\n/)

Tabla (valores a capturar en negrita):

begin 1,699,932 10,136.45
1 1,712,388 12,455.32
2 1,712,605 12,484.85
3 1,712,611 12,513.51

Ojala podáis ayudarme, porque aunque he usado "comprobadores de expresiones regulares" online que me dicen que hace "match", en mi código no parece funcionar...
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Capturar doble salto línea con expresión regular

Notapor explorer » 2023-07-25 04:14 @218

Me extraña que necesites poner '\r' en la expresión regular. Sólo es necesario cuando el texto que estamos analizando proviene de un sistema operativo distinto de en el que estamos.

O sea... si la cuestión es capturar dos valores de una tabla, basta con pedir a split() que parta la línea en columnas, y nos quedaremos con las dos últimas.

Pero... hay una condición más... Deben existir dos saltos de línea.

Si tenemos todo el texto almacenado en una variable, es fácil de encontrar:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.24;
  3.  
  4. my $texto = 'begin 1,699,932 10,136.45
  5. 1 1,712,388 12,455.32
  6. 2 1,712,605 12,484.85
  7. 3 1,712,611 12,513.51
  8.  
  9. ';
  10.  
  11. say "[$texto]";
  12.  
  13. $texto =~ /(\S+) \s+ (\S+) \n \n/sx;
  14.  
  15. say "[$1] [$2]";  # [1,712,611] [12,513.51]
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Capturar doble salto línea con expresión regular

Notapor Alfumao » 2023-07-26 13:23 @599

¡Hola, explorer!

El tema es un poco más complejo en su conjunto.

Tengo que extraer los valores de un archivo que contiene líneas de info, tablas con info, y líneas sin info (te pego un ejemplo debajo). El tema es que mis colaboradores me piden extraer info de todos lados y se me está haciendo un poco bola el asunto...

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Polishing miniasm assembly with Racon (2023-07-08 00:32:20)
-----------------------------------------------------------
    Unicycler now uses Racon to polish the miniasm assembly. It does multiple rounds of polishing to get the best consensus. Circular unitigs are rotated between rounds such that all parts (including the ends) are polished well.

Saving to /storage/Filtered_reads/NKC1231_LRassembly/miniasm_assembly/racon_polish/polishing_reads.fastq:
  38,855 long reads

Polish       Assembly          Mapping
round            size          quality
begin       1,671,271        29,207.18
1           1,685,412        33,629.12
2           1,685,573        33,654.73
3           1,685,628        33,682.91

Best polish: /storage/Filtered_reads/NKC1231_LRassembly/miniasm_assembly/racon_polish/016_rotated.fasta
Saving /storage/Filtered_reads/NKC1231_LRassembly/miniasm_assembly/13_racon_polished.gfa
Saving /storage/Filtered_reads/NKC1231_LRassembly/003_racon_polished.gfa
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


La historia es que me atasco en dos cosas, principalmente:

- Cómo extraer la info de las líneas 2 y 3 de la tabla anterior

- Extraer la siguiente tabla completa en otro archivo (empieza en "Segment" y acaba en "\n\nAssembly") pero por más que intento capturar el rango y quedarme con la tabla no me funciona ninguna expresión regular de las que he probado, p. e.:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. /(?<=Segment)[\S\s](*?)(?=\n\nAssembly)/
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
    Any completed circular contigs (i.e. single contigs which have one link connecting end to start) can have their start position changed without altering the sequence. For consistency, Unicycler now searches for a starting gene (dnaA or repA) in each such contig, and if one is found, the contig is rotated to start with that gene on the forward strand.

Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
      1   1,686,067   1.00x   none found                                            
      2      29,404   2.12x   none found                                            


Assembly complete (2023-07-08 00:57:51)
---------------------------------------
Saving /storage/ONT/NETRAM_Campy/Filtered_reads/NKC1234_LRassembly/assembly.gfa
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Disculpa tanto rollo, pero es que estoy rozando la desesperación, jajajaja

;)
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Capturar doble salto línea con expresión regular

Notapor explorer » 2023-07-26 23:14 @010

Esta es una solución para el primer caso:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use v5.24;
  4. use Path::Tiny;
  5.  
  6. my $archivo = path("kk.txt")->slurp;   # leemos el contenido
  7. #say $archivo;
  8.  
  9. # Buscar por la tabla Polish
  10. # Tratamos archivo como una sola cadena (/s), y
  11. # las anclas ^ y $ detectan posiciones en cualquier parte del texto (/m)
  12. if ($archivo =~ /^(Polish\s+Assembly.+?)\n\n/ms) {
  13.     say "[$1]";
  14.     my $tabla = $1;
  15.  
  16.     # Extraer las dos últimas líneas de la tabla
  17.     # Usamos un truco muy sucio: metemos el texto, separado por líneas,
  18.     # en un array, y nos quedamos con los dos últimos valores
  19.     my @tabla = split /\n/, $tabla;
  20.     say "Dos últimas líneas:\n$tabla[-2]\n$tabla[-1]";
  21. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y este para el segundo caso. No sabemos si forman parte del mismo archivo, pero se pueden aplicar las dos soluciones a la vez, si es el caso.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use v5.24;
  4. use Path::Tiny;
  5.  
  6. my $archivo = path("kk.txt")->slurp;   # leemos el contenido
  7. #say $archivo;
  8.  
  9. # Buscar por la tabla Segment
  10. # La línea comienza por "Segment Length" y termina justo antes de dos avances de línea
  11. my($tabla) = $archivo =~ /^(Segment\s+Length.+?)\n\n/ms;
  12.  
  13. say "[$tabla]";
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: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Capturar doble salto línea con expresión regular

Notapor Alfumao » 2023-07-28 03:15 @177

Hola de nuevo, explorer.

He tenido algunos problemillas con la identificación en el foro y por eso el retraso en contestar...

Te paso un ejemplo de un archivo tipo donde efectivamente se encuentran a la vez todos esos datos que quiero obtener (como la negrita parece no funcionar bien te describo tras el texto principal los datos específicos que no puedo conseguir:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Loading reads (2023-07-08 00:29:15)
-----------------------------------
38,855 / 38,855 (100.0%) - 254,724,562 bp


Assembling contigs and long reads with miniasm (2023-07-08 00:29:21)
--------------------------------------------------------------------
Saving to /storage/C1231_LRassembly/miniasm_assembly/01_assembly_reads.fastq:
  38,855 long reads

Finding overlaps with minimap...
success
  5,947,215 overlaps

Assembling reads with miniasm...
success
  320 segments, 320 links

Saving /storage/C1231_LRassembly/miniasm_assembly/11_branching_paths_removed.gfa
Merging segments into unitigs:
  1 circular unitig
  total size = 1,671,271 bp
Saving /storage/C1231_LRassembly/miniasm_assembly/12_unitig_graph.gfa
Saving /storage/C1231_LRassembly/002_unitig_graph.gfa


Polishing miniasm assembly with Racon (2023-07-08 00:32:20)
-----------------------------------------------------------
    Unicycler now uses Racon to polish the miniasm assembly. It does multiple rounds of polishing to get the best consensus. Circular unitigs are rotated between rounds such that all parts (including the ends) are polished well.

Saving to /storage/C1231_LRassembly/miniasm_assembly/racon_polish/polishing_reads.fastq:
  38,855 long reads

Polish       Assembly          Mapping
round            size          quality
begin       1,671,271        29,207.18
1           1,685,412        33,629.12
2           1,685,573        33,654.73
3           1,685,628        33,682.91

Best polish: /storage/C1231_LRassembly/miniasm_assembly/racon_polish/016_rotated.fasta
Saving /storage/C1231_LRassembly/miniasm_assembly/13_racon_polished.gfa
Saving /storage/C1231_LRassembly/003_racon_polished.gfa


Rotating completed replicons (2023-07-08 00:38:35)
--------------------------------------------------
    Any completed circular contigs (i.e. single contigs which have one link connecting end to start) can have their start position changed without altering the sequence. For consistency, Unicycler now searches for a starting gene (dnaA or repA) in each such contig, and if one is found, the contig is rotated to start with that gene on the forward strand.

Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
      1   1,685,628   1.00x   none found                                            
      2     585,617   1.00x   none found  




Assembly complete (2023-07-08 00:39:06)
---------------------------------------
Saving /storage/C1231_LRassembly/assembly.gfa

 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Datos 1. Las dos últimas líneas de esta tabla (el número de líneas es variable en cada archivo de resultados):


Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Polish       Assembly          Mapping
round            size          quality
begin       1,671,271        29,207.18
1           1,685,412        33,629.12
2           1,685,573        33,654.73
3           1,685,628        33,682.91
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Datos 2. Esta tabla completa (como en el caso anterior el número de líneas es variable en cada archivo de resultados)

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
      1   1,685,628   1.00x   none found                                            
      2     585,617   1.00x   none found
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

La idea sería tener todo el proceso en un mismo código.

Por ahora he conseguido obtener todos los datos anteriores que necesito además de la última línea de la primera tabla con este código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!usr/bin/perl -w
  2. use strict;
  3. use Getopt::Long;
  4.  
  5. my ($path, $study);
  6. GetOptions(
  7.     'path=s'          => \$path,
  8.     );
  9.    
  10. print "$path\n";
  11. chdir $path or die "ERROR: Unable to enter $path: $!\n";
  12. opendir (TEMP , ".");
  13. my @files = readdir (TEMP);
  14. closedir TEMP;
  15.  open  OUT,'>'."Unicycler_logs_parsed.tsv" or die "ERROR: Unable to open outfile $!\n";
  16.  print OUT "Sample\tInput_Reads\tInput_bp\tCircular_contigs\tLinear_contigs\tTotal_size_bp_before_polish\tmax_score_after_polish\tfinal_size_after_polish\n";
  17.          
  18.  
  19. for my $file (@files) {
  20.  
  21. my$inputreads;
  22. my$perc;
  23. my$inputbp;
  24. my$tsizbpol;
  25. my$linear=0;
  26. my$circ=0;
  27.  my ( $inputreads, $perc, $inputbp, $tsizbpol, $found, $mAxssize, $qualAssize );
  28.  
  29.     if($file=~/(\w+)\_LRassembly.unicycler.log/){
  30.           my$sample=$1;
  31.           print OUT "$sample\t";
  32.           print "Sample is $sample\n";
  33.  
  34.           open(INFILE,"$file") or die ("ERROR: Unable to open Log to parse file $!\n");
  35.           chomp(my @data = <INFILE>);
  36.           print"Parsing $file\n";
  37.           my$nc=0;
  38.  
  39.  
  40.         for (@data) {
  41.  
  42.             if($_=~/^([\d+\,]+)\s\/\s([\d+\,]+)\s\(([\d+\.]+)\%\)\s\-\s([\d+\,]+)\sbp/){
  43.                     $inputreads=$1;
  44.                     print "IN $inputreads\n";
  45.                     $perc=$3;
  46.                     print "Perc $perc\n";
  47.                     $inputbp=$4;
  48.                     print "INbp $inputbp\n";
  49.             }
  50.             if($_=~/total size\s\=\s([\d+\,]+)\sbp/){
  51.                     $tsizbpol=$1;
  52.                     print "Total Size before polish $tsizbpol $!\n";
  53.             }
  54.             if($_=~/(\d+)\s+linear unitig/ || /(\d)\s+linear unitigs/){
  55.                    $linear=$1;
  56.                    print "linear unitigs $circ $!\n";
  57.             }
  58.            if($_=~/(\d+)\s+circular unitig/ || /(\d)\s+circular unitigs/){
  59.                     $circ=$1;
  60.                     print "circular unitigs $circ $!\n";
  61.             }
  62.    
  63.     }
  64.          print OUT ("$inputreads\t$inputbp\t$linear\t$circ\t$tsizbpol\t") or die ("ERROR: Unable to write log parsing file $!\n");    
  65.          open( my $INFILE, "<", $file )or die( "ERROR: Can't open log file `$file`: $!\n" );  # Incl file name
  66.  
  67.    
  68.         while ( <$INFILE> ) {
  69.               s/\s+\z//;  # Remove line endings. Handles both `\n` and `\r\n`.
  70.              if ( $found && !length( $_ ) ) {
  71.                  print "MaxAssemblySize $mAxssize\n";
  72.                  print "QualAssembly $qualAssize\n";
  73.                  print OUT ("$qualAssize\t$mAxssize\n") or die ("ERROR: Unable to write log parsing file $!\n");
  74.                  }
  75.  
  76.                 $found = ( $mAxssize, $qualAssize ) = /([\d+\,]+)\s+([\d+\,]+\.\d+)\z/;
  77.  
  78.         }
  79.  
  80.      }
  81. }
  82.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

¿Cómo lo ves?
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Capturar doble salto línea con expresión regular

Notapor explorer » 2023-07-28 14:59 @666

Probando, sale esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Sample  Input_Reads     Input_bp        Circular_contigs        Linear_contigs  Total_size_bp_before_polish     max_score_after_polish  final_size_after_polish
inicio  38,855          254,724,562     0                       1               1,671,271                       33,682.91               1,685,628
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Salvo el detalle que Circular_contigs y Lineas_contigs están al revés, se supone que están todos los datos que necesitas, ¿no?

No entiendo lo de "las dos últimas líneas de la tabla". ¿Cómo tendrían que salir esas dos líneas? Yo lo que veo es que capturas las dos últimas columnas, de la última línea.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Capturar doble salto línea con expresión regular

Notapor Alfumao » 2023-07-29 02:27 @144

Hola, explorer.

Como bien dices, en el script capturo las 2 últimas columnas de la última línea, pero ahora me piden que capture también esas mismas columnas en la línea anterior y después compare los valores de max_score_after_polish de ambas líneas, para así seleccionar e imprimir en la tabla de salida los valores de la línea que tenga ese parámetro más alto...

Y luego falta también lo de la captura de la tabla del final, que es otro quebradero de cabeza.

Cada día una cosa nueva, me solicitan...
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Capturar doble salto línea con expresión regular

Notapor explorer » 2023-07-29 18:46 @823

Primero, detalles basados en el código que has mostrado antes.

  • Línea 1: falta un '/' delante de usr.
  • Línea 1: no es recomendable usar "-w" ya que eso activa las advertencias incluso en los módulos externos. Mejor usar "use warnings;".
  • Línea 1: agrega la línea 'use warnings;' para que Perl te avise de más problemas.
  • Líneas 15, 16, 31... (todas las que son OUT). Lo mejor sería acumular la información y mostrarla al final con el formato que nos piden, pero debemos saberlo. Mientras tanto, tendrás que acomodarte a lo que te piden
  • La línea 27 genera advertencias porque estás declarando las mismas variables dos veces.
  • Línea 35. Ya que te has leído el archivo entero, y luego lo vuelves a abrir en la línea 65, es recomendable poner un 'close INFILE;'.
  • Línea 56. Hay un error con la variable. Debe ser $linear.
  • Línea 64. El orden de impresión de $linear y $circ es incorrecto.
  • Bucle 68 a 78. Con ese bucle capturas la información de la última línea, pero no de las anteriores. La clave está en la comprobación length($_) que marca la primera línea en blanco justo después de la última línea. Ya que vas a necesitar recordar varias líneas, casi mejor hacer un bucle que las lea todas, y cuando termines, accedes a las últimas con los índices [-2] y [-1], como te indicaba en mi anterior respuesta.
Un comentario... el formato del log sigue una serie de reglas sencillas por las que es fácil "partirlo". Veo que son distintas secciones que comienzan con un título, seguido por una línea de guiones, y termina con 3 o más avances de línea consecutivos, o el final de archivo. Esto es más que suficiente para poder procesar todo el registro y sacar información.

Esta es mi solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #
  3. # Procesar registro generado por Unicycler
  4. #
  5. # Joaquín Ferrero, julio 2023
  6. #
  7. # Primera versión: 20230729
  8. #
  9.  
  10. use v5.24;              # mínima versión de Perl
  11. use strict;             # programación estricta
  12. use warnings;           # activar advertencias
  13.  
  14. use Getopt::Long;
  15. use autodie;            # para toda la E/S
  16.  
  17. ## Constantes
  18. my $PLANTILLA_INFORMES  = qr/(\w+)\_LRassembly[.]unicycler[.]log/;
  19. my $ARCHIVO_SALIDA      = 'Unicycler_logs_parsed.tsv';
  20.  
  21. #         1         2         3         4         5         6         7         8         9        10        11        12        13        14        15        16
  22. #1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
  23. #Sample   Input_Reads     Input_bp      Circular_contigs    Linear_contigs      Total_size_bp_before_polish   max_score_after_polish   final_size_after_polish
  24. #inicio   38,855          254,724,562   0                   1                   1,671,271                     33,682.91                1,685,628
  25. my @CABECERAS        = qw(Sample Input_Reads Input_bp Circular_contigs Linear_contigs Total_size_bp_before_polish max_score_after_polish final_size_after_polish);
  26. my @ANCHOS_CABECERAS = qw(7      15          15       23               15             31                          23                     23                     );
  27. my $FORMATO_SALIDA   = join(" ", map { "%-${_}s" } @ANCHOS_CABECERAS) . "\n";
  28.  
  29. my $DEFINES          = qr/(?(DEFINE)(?<NUMERO>[\d,]+(?:[.]\d+)?))/x;
  30.  
  31. ## Argumentos
  32. # Ruta a la carpeta a procesar
  33. my $path;
  34. GetOptions(
  35.     'path=s'    => \$path,
  36. );
  37. $path           or die "Uso: $0 -path=<carpeta con registros a procesar>\n";
  38. -d $path        or die "ERROR: la carpeta no existe: $!\n";
  39. chdir $path     or die "ERROR: no puedo entrar en [$path]: $!\n";
  40.  
  41. ## Procesamiento
  42. # Lista de archivos identificados como informes
  43. my @archivos;
  44. opendir (my $DIR , ".");
  45. while (my $archivo = readdir $DIR) {
  46.     next if $archivo !~ $PLANTILLA_INFORMES;
  47.     push @archivos, $archivo;
  48. }
  49. closedir $DIR;
  50.  
  51. # Si hay archivos que procesar, los procesamos
  52. if (@archivos) {
  53.     open my $OUT, '>', $ARCHIVO_SALIDA;
  54.     printf  $OUT $FORMATO_SALIDA, @CABECERAS;
  55.  
  56.     my @salida;
  57.  
  58.     for my $archivo (@archivos) {
  59.  
  60.         # Leer archivo
  61.         my $informe;
  62.         if (open my $IN, '<', $archivo) {
  63.             local $/;           # modo aspiradora
  64.             $informe = <$IN>;
  65.             close $IN;
  66.         }
  67.  
  68.         # Sample
  69.         push @salida, $archivo =~ $PLANTILLA_INFORMES;
  70.  
  71.         # Loading reads
  72.         # -------------
  73.         if ($informe =~ m{
  74.                 ^ Loading [ ] reads .+? \n
  75.                 -+ \n
  76.                 (?<INPUTREAD>(?&NUMERO)) [ ] / [ ] (?&NUMERO) [ ] \( (?&NUMERO) % \) [ ] - [ ] (?<INPUTBP>(?&NUMERO)) [ ] bp
  77.                 $DEFINES
  78.             }msx
  79.         ) {
  80.             push @salida, convierte($+{INPUTREAD}), convierte($+{INPUTBP});
  81.         }
  82.  
  83.         # Assembling contigs
  84.         if ($informe =~ m{
  85.                 ^ Assembling [ ] contigs .+? \n
  86.                 -+ \n
  87.                 (.+?) \n{3}
  88.             }msx
  89.         ) {
  90.             my $assembly = $1;
  91.  
  92.             my($lin_unitig) = $assembly =~ /^\s*(\d+) linear unitig/m;
  93.             my($cir_unitig) = $assembly =~ /^\s*(\d+) circular unitig/m;
  94.             my($total_bp)   = $assembly =~ /total size = (?<TOTALBP>(?&NUMERO)) bp$DEFINES/m;
  95.             $lin_unitig ||= 0;
  96.             $cir_unitig ||= 0;
  97.             $total_bp     = convierte($total_bp);
  98.  
  99.             push @salida, $cir_unitig, $lin_unitig, $total_bp;
  100.         }
  101.  
  102.         # Polishing miniasm assembly with Racon
  103.         if ($informe =~ m{
  104.                 ^ Polishing [ ] miniasm [ ] assembly .+? \n
  105.                 -+ \n
  106.                 (.+?) \n{3}
  107.             }msx
  108.         ) {
  109.             my $polish = $1;
  110.             # Extraer la tabla de datos
  111.             my @tabla;
  112.             for (split /\n/, $polish) {
  113.                 if (/^Polish/ .. /^$/) {
  114.                     push @tabla, $_;
  115.                 }
  116.             }
  117.             # Buscar el máximo
  118.             my($max_assembly, $max_qa) = (0, 0);
  119.             if (@tabla) {
  120.                 # las dos últimas filas
  121.                 for (@tabla[-2, -1]) {
  122.                     # partimos la línea en tres partes
  123.                     if (my(undef, $assembly, $qa) = split " ") {
  124.                         $assembly = convierte($assembly);
  125.                         $qa       = convierte($qa);
  126.                         # nos quedamos con el mayor valor de quality
  127.                         if ($max_qa < $qa) {
  128.                             $max_qa = $qa;
  129.                             $max_assembly = $assembly;
  130.                         }
  131.                     }
  132.                 }
  133.             }
  134.             push @salida, $max_qa, $max_assembly;
  135.         }
  136.        
  137.         printf $OUT $FORMATO_SALIDA, @salida;
  138.  
  139.         # Rotating completed replicons
  140.         if ($informe =~ m{
  141.                 ^ Rotating [ ] completed [ ] replicons .+?
  142.                 ( ^ Segment .+? )
  143.                 \n{2}
  144.             }msx
  145.         ) {
  146.             print $OUT "$1\n";
  147.         }
  148.  
  149.     } # next $archivo
  150.  
  151.     close   $OUT;
  152. }
  153.  
  154. # Convierte de notación inglesa a española
  155. sub convierte {
  156.     my $numero = shift;
  157.     $numero =~ s/,//g;
  158.     $numero += 0;
  159.     return $numero;
  160. }
  161.  
  162. __END__
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4

Esta es la salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Sample  Input_Reads     Input_bp        Circular_contigs        Linear_contigs  Total_size_bp_before_polish     max_score_after_polish  final_size_after_polish
inicio  38855           254724562       1                       0               1671271                         33682.91                1685628                
Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
      1   1,685,628   1.00x   none found                                            
      2     585,617   1.00x   none found  
Coloreado en 0.000 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: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Capturar doble salto línea con expresión regular

Notapor Alfumao » 2023-08-04 06:10 @298

Hola de nuevo, explorer.

He modificado tu script para que cumpla con las necesidades reales, que son:

  1. Poder procesar cientos de logs presentes en un mismo directorio para sacar una tabla que les incluya a todos, que esté separada por tabuladores y sea fácilmente exportable a Excel, si fuera el caso (eliminé el formato que le diste a las cabeceras e incluí un reinicio del array de datos para que pudieran caber logs secuencialmente).

    Ejemplo del formato:
    Sintáxis: (Unicycler_logs_parsed_3.tsv) [ Descargar ] [ Ocultar ]
    Using text Syntax Highlighting
    Sample  Input_Reads     Input_bp        Circular_contigs        Linear_contigs  Total_size_bp_before_polish     max_score_after_polish  final_size_after_polish
    HUBC50765343    14736   87790955        1       0       1708070 11851.41        1728821
    HUBC51089086    12307   43200839        0       12      1189336 6080.87 1202453
    HUBC51130095    14780   30530573        0       9       115115  1009.79 117534
    HUBC52251288    30933   70953558        0       41      1635213 16833.84        1655600
    Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

  2. Obtener, por un lado una tabla con los parámetros de interés y por otro un archivo donde encontremos la tabla de contigs de todos esos logs, precedida por el nombre del log que se procesa (añadí la impresión del nombre del archivo precediendo a la tabla y las saqué a una salida diferente a la de los otros datos).

    Ejemplo del formato:
    Sintáxis: (Unicycler_tables_3.tsv) [ Descargar ] [ Ocultar ]
    Using text Syntax Highlighting
    HUBC50765343_LRassembly.unicycler.log
    Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
          1   1,728,821   1.00x   none found                                            
    HUBC56801624_LRassembly.unicycler.log
    Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
          1   1,622,619   1.00x   none found                                            
    HUDC61355553_LRassembly.unicycler.log
    Segment   Length      Depth   Starting gene   Position   Strand   Identity   Coverage
          1   1,679,694   1.00x   none found                                            
          2      47,978   0.94x   none found                                            
    Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Y aquí te dejo el script final.
Sintáxis: (UnicExplorer_JL.pl) [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #
  3. # Procesar registro generado por Unicycler
  4. #
  5. # Joaquín Ferrero, julio 2023 (adaptado por JLL, agosto 2023)
  6. #
  7. # tercera versión: 20230806
  8. #
  9. # usage example:
  10. #
  11. #    perl UnicExplorer_JL.pl -p /path_to_files
  12. #
  13.  
  14. use v5.24;              # mínima versión de Perl
  15. use strict;             # programación estricta
  16. use warnings;           # activar advertencias
  17.  
  18. use Getopt::Long;
  19. use autodie;            # para toda la E/S
  20.  
  21.  
  22. ## Constantes #####################################################
  23. my $PLANTILLA_INFORMES  = qr/(\w+)\_LRassembly[.]unicycler[.]log/;
  24. my $ARCHIVO_SALIDA      = 'Unicycler_logs_parsed_3.tsv';
  25. my $ARCHIVO_SALIDA2     = 'Unicycler_tables_3.tsv';
  26. my @CABECERAS           = qw(
  27.      Sample Input_Reads Input_bp Circular_contigs Linear_contigs
  28.      Total_size_bp_before_polish max_score_after_polish final_size_after_polish
  29. );
  30. my $DEFINES             = qr/(?(DEFINE)(?<NUMERO>[\d,]+(?:[.]\d+)?))/x;
  31.  
  32. ## Argumentos #####################################################
  33. # Ruta a la carpeta a procesar
  34. my $path;
  35. GetOptions(
  36.     'path=s'    => \$path,
  37. );
  38. $path           or die "Uso: $0 -path=<carpeta con registros a procesar>\n";
  39. -d $path        or die "ERROR: la carpeta no existe: $!\n";
  40. chdir $path     or die "ERROR: no puedo entrar en [$path]: $!\n";
  41.  
  42. ## Procesamiento ##################################################
  43. # Lista de archivos identificados como informes
  44. my @archivos;
  45. opendir (my $DIR , ".");
  46. while (my $archivo = readdir $DIR) {
  47.     next if $archivo !~ $PLANTILLA_INFORMES;
  48.     push @archivos, $archivo;
  49. }
  50. closedir $DIR;
  51.  
  52. # Si hay archivos que procesar, los procesamos
  53. if (@archivos) {
  54.     open my $OUT, '>', $ARCHIVO_SALIDA;
  55.     print $OUT join("\t", @CABECERAS), "\n";
  56.  
  57.     open my $OUT2, '>', $ARCHIVO_SALIDA2;
  58.  
  59.     for my $archivo (@archivos) {
  60.         my @salida;
  61.         # Leer archivo
  62.         my $informe;
  63.         if (open my $IN, '<', $archivo) {
  64.             local $/;           # modo aspiradora
  65.             $informe = <$IN>;
  66.             close $IN;
  67.         }
  68.         # Sample
  69.         push @salida, $archivo =~ $PLANTILLA_INFORMES;
  70.  
  71.         # Loading reads
  72.         # -------------
  73.         if ($informe =~ m{
  74.                 ^ Loading [ ] reads .+? \n
  75.                 -+ \n
  76.                 (?<INPUTREAD>(?&NUMERO)) [ ] / [ ] (?&NUMERO) [ ] \( (?&NUMERO) % \) [ ] - [ ] (?<INPUTBP>(?&NUMERO)) [ ] bp
  77.                 $DEFINES
  78.             }msx
  79.         ) {
  80.             push @salida, convierte($+{INPUTREAD}), convierte($+{INPUTBP});
  81.         }
  82.  
  83.         # Assembling contigs
  84.         # ------------------
  85.         if ($informe =~ m{
  86.                 ^ Assembling [ ] contigs .+? \n
  87.                 -+ \n
  88.                 (.+?) \n{3}
  89.             }msx
  90.         ) {
  91.             my $assembly = $1;
  92.  
  93.             my($lin_unitig) = $assembly =~ /^\s*(\d+) linear unitig/m;
  94.             my($cir_unitig) = $assembly =~ /^\s*(\d+) circular unitig/m;
  95.             my($total_bp)   = $assembly =~ /total size = (?<TOTALBP>(?&NUMERO)) bp$DEFINES/m;
  96.             $lin_unitig   ||= 0;
  97.             $cir_unitig   ||= 0;
  98.             $total_bp       = convierte($total_bp);
  99.  
  100.             push @salida, $cir_unitig, $lin_unitig, $total_bp;
  101.         }
  102.  
  103.         # Polishing miniasm assembly with Racon
  104.         # -------------------------------------
  105.         if ($informe =~ m{
  106.                 ^ Polishing [ ] miniasm [ ] assembly .+? \n
  107.                 -+ \n
  108.                 (.+?) \n{3}
  109.             }msx
  110.         ) {
  111.             my $polish = $1;
  112.  
  113.             # Extraer la tabla de datos
  114.             my @tabla;
  115.             for (split /\n/, $polish) {
  116.                 if (/^Polish/ .. /^$/) {
  117.                     push @tabla, $_;
  118.                 }
  119.             }
  120.  
  121.             # Buscar el máximo
  122.             my($max_assembly, $max_qa) = (0, 0);
  123.             if (@tabla) {
  124.                 # las dos últimas filas
  125.                 for (@tabla[-2, -1]) {
  126.                     # partimos la línea en tres partes
  127.                     if (my(undef, $assembly, $qa) = split " ") {
  128.                         $assembly = convierte($assembly);
  129.                         $qa       = convierte($qa);
  130.                         # nos quedamos con el mayor valor de quality
  131.                         if ($max_qa < $qa) {
  132.                             $max_qa = $qa;
  133.                             $max_assembly = $assembly;
  134.                         }
  135.                     }
  136.                 }
  137.             }
  138.             push @salida, $max_qa, $max_assembly;
  139.         }
  140.         print $OUT join("\t", @salida), "\n";      # print tab separated array in OUTFILE
  141.  
  142.         # Rotating completed replicons
  143.         # ----------------------------
  144.         if ($informe =~ m{
  145.                 ^ Rotating [ ] completed [ ] replicons .+?
  146.                 ( ^ Segment .+? )
  147.                 \n{2}
  148.             }msx
  149.         ) {
  150.             print $OUT2 "$archivo\n$1\n";
  151.         }
  152.  
  153.     } # next $archivo
  154.  
  155.     close   $OUT;
  156.     close   $OUT2;
  157. }
  158.  
  159. # Convierte de notación inglesa a española
  160. sub convierte {
  161.     my $numero = shift;
  162.     $numero =~ s/,//g;
  163.     $numero += 0;
  164.     return $numero;
  165. }
  166.  
  167. __END__
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Muchísimas gracias una vez más por tu ayuda, ¡eres un super crack!

:D ;)
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Capturar doble salto línea con expresión regular

Notapor explorer » 2023-08-06 01:34 @107

Le he hecho un par de cambios:

* añadir un close $OUT2;

* cambiar de posición my @salida;, dentro del for(), para que así no tengas que resetearlo en cada vuelta.

* formateo del código.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado