Página 1 de 2

Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-01 19:34 @857
por felloz
Un saludo.

Tengo este código con el que busco hasta el final de la línea pero me gustaría que buscara hasta que se encuentre un punto, para que me extraiga un texto con coherencia.

A continuación el código:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. my $body;
  7. my $smtpCode;
  8.  
  9. $body = "Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does
  10.    not exist. Please try 550-5.1.1 double-checking the recipient's email
  11.    address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1
  12.    https://support.google.com/mail/?p=NoSuchUser s35si4587705qvc.145 - gsmtp";
  13.  
  14. foreach ( split( /\n/, $body ) ) {
  15.     next if (/^\s*$/);
  16.  
  17.     if ( $_ =~ /^Diagnostic-Code:\ssmtp;\s(.*)$/ ) {
  18.         $smtpCode = $1;
  19.         print $smtpCode;                       # Salida: 550-5.1.1 The email account that you tried to reach does
  20.  
  21.     }
  22. }
  23.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Y lo que realmente me gustaría que mostrara es lo siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. 550-5.1.1 The email account that you tried to reach does
  2. not exist.
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

O que por lo menos muestre todo el párrafo después de Diagnostic-Code: smtp;

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. 550-5.1.1 The email account that you tried to reach does
  2. not exist. Please try 550-5.1.1 double-checking the recipient's email
  3. address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1
  4. https://support.google.com/mail/?p=NoSuchUser s35si4587705qvc.145 - gsmtp
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Muchas gracias.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-02 02:32 @147
por explorer
Se podría resolver con un rango:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $body = "Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does
  6.    not exist. Please try 550-5.1.1 double-checking the recipient's email
  7.    address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1
  8.    https://support.google.com/mail/?p=NoSuchUser s35si4587705qvc.145 - gsmtp";
  9.  
  10. my $resultado;
  11.  
  12. for ( split /\n/, $body ) {
  13.     next if /^\s*$/;                            # saltamos líneas en blanco
  14.  
  15.     s/^\s+//;                                   # quitamos espacios iniciales de la línea
  16.  
  17.     # si estamos en el rango "Diagnostic" ... punto+espacio o fin de archivo
  18.     if ( my $en_rango = /^Diagnostic-Code:\ssmtp;/ .. (/\. / || eof) ) {
  19.         my $linea = $_;
  20.  
  21.         if ($en_rango == 1) {                   # si es la primera...
  22.             $linea =~ s/^Diagnostic-Code:\ssmtp;\s//;
  23.         }
  24.         elsif ($en_rango =~ /E0$/) {            # si es la última línea...
  25.             $linea =~ s/\.\K.*//;               # quitamos lo que hay después del punto
  26.         }
  27.  
  28.         if ($resultado) {                       # acumulamos la $linea al $resultado
  29.             $resultado .= " $linea";
  30.         }
  31.         else {
  32.             $resultado = $linea;
  33.         }
  34.     }
  35. }
  36.  
  37. print "[$resultado]\n";                         # [550-5.1.1 The email account that you tried to reach does not exist.]
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

pero... sería mejor tener más información de cómo es el texto de donde queremos extraer esa información. Si es un registro de actividad (log), ese texto vendrá en una sola línea, por lo que la solución es más sencilla.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-02 09:20 @430
por felloz
Muchas gracias por tu respuesta.

En el caso de que quiera retirar de la variable $resultado el texto Diagnostic-Code: smtp;, ¿me recomiendas hacerlo con la función substr()?

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-02 09:43 @447
por explorer
Se puede hacer, pero es mucho más cómodo usar una operación de sustitución s///.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-02 10:20 @472
por felloz
explorer escribiste:Se puede hacer, pero es mucho más cómodo usar una operación de sustitución s///.


Excelente

Sintáxis: [ Descargar ] [ Ocultar ]
  1. $resultado =~ s/Diagnostic-Code: smtp;//;  

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-03 09:59 @457
por felloz
Me he percatado de algo interesante: ¿Qué pasaría si ese dato yo lo quisiera ingresar en un campo de una base de datos? ¿Qué pasaría si ese texto contiene comillas simples? Pasaría que la consulta destinada al hacer el INSERT fallaría y no podría registrar los datos.

Se me ocurrió utilizar la función que me recomendaste (s///) pero, ¿qué pasaría si hay más de una comilla? Pues ahí fue donde se me ocurrió usar un while(), pero ocurre algo. A pesar de que el texto se almacena en toda la variable parece que el salto de página persiste en la variable $resultado y si la comilla está en la segunda línea no las extrae.

Hasta aquí pude avanzar, cualquier ayuda estaría agradecido.

Sintáxis: [ Descargar ] [ Ocultar ]
  1. use strict; 
  2. use warnings; 
  3.  
  4. my $body = "Diagnostic-Code: smtp; 550-5.1.1 The email's account that you tr'ied to re'ach do'es 
  5.   n'ot 'exist. Please try 550-5.1.1 double-checking the recipient's email 
  6.   address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1 
  7.   https://support.google.com/mail/?p=NoSuchUser s35si4587705qvc.145 - gsmtp"; 
  8.  
  9. my $resultado; 
  10.  
  11. for ( split /\n/, $body ) { 
  12.   next if /^\s*$/;              # saltamos líneas en blanco 
  13.  
  14.   s/^\s+//;                  # quitamos espacios iniciales de la línea 
  15.  
  16.   # si estamos en el rango "Diagnostic" ... punto+espacio o fin de archivo 
  17.   if ( my $en_rango = /^Diagnostic-Code:\ssmtp;\s(.*)$/ .. (/\. / || eof ) ) { 
  18.     my $linea = $_; 
  19.     if ($en_rango =~ /E0$/) {        # si es la última línea, 
  20.       $linea =~ s/\.\K.*//;        # quitamos lo que hay después del punto 
  21.     } 
  22.     if ($resultado) {            # acumulamos la $linea al $resultado 
  23.       $resultado .= " $linea"; 
  24.     } 
  25.     else { 
  26.       $resultado = $linea; 
  27.       $resultado =~ s/Diagnostic-Code: smtp;//;  
  28.       while($resultado =~ /'/){ 
  29.         $resultado =~ s/'//; 
  30.       } 
  31.     } 
  32.   } 
  33.  
  34. print "$resultado\n"; #Mostrará: 550-5.1.1 The emails account that you tried to reach does n'ot 'exist. 

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-03 11:22 @515
por explorer
No necesitas quitar las comillas.

Si haces la consulta con el sistema de "placeholders" del módulo DBI, es el propio DBI el que se encarga de "escapar" esos caracteres peligrosos.

Mira este código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $sth = $dbh->prepare('INSERT INTO tabla VALUES( ?, ? )');
  2. $sth->execute( $id, $resultado );
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En la primera línea llamamos al método prepare() con la consulta SQL que queremos ejecutar. Es igual a cualquier otra consulta, pero aparecen un par de caracteres '?'. Estos son los que se llaman "placeholder" o guardasitios. El DBI "prepara" la consulta, pero no la ejecuta.

Luego, en la segunda línea es cuando ejecutamos la consulta, pero pasando dos argumentos. Cada argumento se "colocará" en su "placeholder" correspondiente, escapando los caracteres peligrosos. Luego ejecuta la consulta.

Otro ejemplo más sencillo y enlaces.

Sobre la forma de quitar las comillas... hay otra forma más cómoda: sustitución global (/g), sin necesidad de bucles.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$resultado =~ s/'//g;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


No nos has dicho nada de cómo es la información en origen. ¿Realmente te llega en varias líneas o solo en una? Ese tipo de mensajes les veo con frecuencia en nuestros servidores, y llegan en una sola línea. Si es así, la solución se acorta bastante.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-03 12:07 @547
por felloz
La información de origen es una bandeja de correos con sus cabeceras. Pero básicamente la información viene muy parecida en como la presenté en la variable, en algunos casos puede venir con comillas simples y nos puede arrojar un error SQL. Quiero prever la situación, pensé en hacerla con la función para no meternos con los query.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-03 12:30 @562
por explorer
Entonces con el sistema de "placeholder" lo tienes resuelto, no tienes que quitar nada.

Re: Buscar y almacenar párrafo o hasta determinado símbolo

NotaPublicado: 2019-09-03 12:47 @574
por felloz
explorer escribiste:Entonces con el sistema de "placeholder" lo tienes resuelto, no tienes que quitar nada.


El problema es que la persona que construyó el codigó inicial para hacer los INSERT en la base de datos lo hizo de una manera que no sé si fue la mejor pero creo que tendríamos que hacer cambios importantes en el código.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         for my $row ( sort keys %devueltos ) {
  2.  
  3.             $query        = undef;
  4.             $queryColumns = undef;
  5.             $queryValues  = undef;
  6.  
  7.             if ( exists( $campanas{ $devueltos{$row}{'campanaid'} } ) ) {
  8.                 $campanas{ $devueltos{$row}{'campanaid'} }{'count'}++;
  9.                 $campanas{ $devueltos{$row}{'campanaid'} }{'adminid'} = $devueltos{$row}{'adminid'};
  10.             }
  11.             else {
  12.                 $campanas{ $devueltos{$row}{'campanaid'} }{'count'}   = 1;
  13.                 $campanas{ $devueltos{$row}{'campanaid'} }{'adminid'} = $devueltos{$row}{'adminid'};
  14.             }
  15.  
  16.             if ( defined $devueltos{$row}{'smtpcode'} ) {
  17.                 $queryColumns .= "smtpcode1, ";
  18.                 $queryValues  .= " '" . $devueltos{$row}{'smtpcode'} . "', ";
  19.             }
  20.             if ( defined $devueltos{$row}{'email'} ) {
  21.                 $queryColumns .= "email, ";
  22.                 $queryValues  .= " '" . $devueltos{$row}{'email'} . "', ";
  23.             }
  24.             if ( defined $devueltos{$row}{'smtpaction'} ) {
  25.                 $queryColumns .= "smtpaction, ";
  26.                 $queryValues  .= " '" . $devueltos{$row}{'smtpaction'} . "', ";
  27.             }
  28.             if ( defined $devueltos{$row}{'smtpstatus'} ) {
  29.                 $queryColumns .= "smtpcode, ";
  30.                 $queryValues  .= " '" . $devueltos{$row}{'smtpstatus'} . "', ";
  31.             }
  32.             if ( defined $devueltos{$row}{'smtpdiagnosticcode'} ) {
  33.                 my $deletechar = $devueltos{$row}{'smtpdiagnosticcode'} =~ s/'//g;
  34.                 $queryColumns .= "smtpprefixdetail, ";
  35.  
  36.                 #$queryValues .= " E'".encode('utf8', decode('iso-8859-1', $devueltos{$row}{'smtpdiagnosticcode'}))."', ";
  37.                 $queryValues .= " '" . encode( 'utf8', decode( 'iso-8859-1', $deletechar ) ) . "', ";
  38.             }
  39.             if ( defined $devueltos{$row}{'smtpremotemta'} ) {
  40.                 $queryColumns .= "smtpremote, ";
  41.                 $queryValues  .= " '" . $devueltos{$row}{'smtpremotemta'} . "', ";
  42.             }
  43.             if ( defined $devueltos{$row}{'smtplastattempdate'} ) {
  44.                 $queryColumns .= "smtpdate, ";
  45.                 $queryValues  .= " '" . $devueltos{$row}{'smtplastattempdate'} . "', ";
  46.             }
  47.             if ( defined $devueltos{$row}{'userid'} ) {
  48.                 $queryColumns .= "id_usuario, ";
  49.                 $queryValues  .= "$devueltos{$row}{'userid'}, ";
  50.             }
  51.             if ( defined $devueltos{$row}{'adminid'} ) {
  52.                 $queryColumns .= "id_admin, ";
  53.                 $queryValues  .= "$devueltos{$row}{'adminid'}, ";
  54.             }
  55.             if ( defined $devueltos{$row}{'campanaid'} ) {
  56.                 $queryColumns .= "id_campana, ";
  57.                 $queryValues  .= "$devueltos{$row}{'campanaid'}, ";
  58.             }
  59.             if ( defined $devueltos{$row}{'listaid'} ) {
  60.                 $queryColumns .= "id_lista, ";
  61.                 $queryValues  .= "$devueltos{$row}{'listaid'}, ";
  62.             }
  63.             if ( defined $devueltos{$row}{'status'} ) {
  64.                 $queryColumns .= "status, ";
  65.                 $queryValues  .= "true, ";
  66.             }
  67.  
  68.             $queryColumns .= "fecha ";
  69.             $queryValues  .= "now() ";
  70.  
  71.             $query = "INSERT INTO ex_tbl_devueltos ($queryColumns) VALUES ($queryValues);";
  72.             $string .= $query . "\n";
  73.             $sth = $dbh->prepare($query) or die "Can't prepare SQL statement: ", $dbh->errstr(), "\n";
  74.             $sth->execute() or die "Can't execute SQL statement: ", $sth->errstr(), "\n";
  75.  
  76.         }
  77.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4