• Publicidad

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

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

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

Notapor felloz » 2019-09-01 19:34 @857

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.002 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.
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

Publicidad

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

Notapor explorer » 2019-09-02 02:32 @147

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.
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: Buscar y almacenar párrafo o hasta determinado símbolo

Notapor felloz » 2019-09-02 09:20 @430

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()?
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

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

Notapor explorer » 2019-09-02 09:43 @447

Se puede hacer, pero es mucho más cómodo usar una operación de sustitución s///.
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: Buscar y almacenar párrafo o hasta determinado símbolo

Notapor felloz » 2019-09-02 10:20 @472

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;//;  
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

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

Notapor felloz » 2019-09-03 09:59 @457

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. 
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

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

Notapor explorer » 2019-09-03 11:22 @515

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.
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: Buscar y almacenar párrafo o hasta determinado símbolo

Notapor felloz » 2019-09-03 12:07 @547

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.
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

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

Notapor explorer » 2019-09-03 12:30 @562

Entonces con el sistema de "placeholder" lo tienes resuelto, no tienes que quitar nada.
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: Buscar y almacenar párrafo o hasta determinado símbolo

Notapor felloz » 2019-09-03 12:47 @574

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
Avatar de Usuario
felloz
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2018-12-10 09:11 @424

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados