• Publicidad

Recorrido de cadenas y separación de campos

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

Notapor explorer » 2006-10-03 05:34 @273

El problema es de concepto:
Ahora no hay que mirar si lo que hemos leído corresponde a una forma u otra de trama o mensaje de ordenes o un estoy vivo, si no que vamos a colocar una batería de 'if' y por cada uno de ellos preguntaremos si la $linea leída corresponde con lo que esperamos. Si es así, entonces hacemos uso de los $campos para sacar la información.

Eso quiere decir que algunas de las cosas que hay en el programa ya no tienen sentido, como lo del 'next unless ...' porque eso servía para cuando sabíamos que sólo ibamos a recibir un cierto tipo de tramas.

El esquema del programa quedaría así:
Código: Seleccionar todo
* Inicialización
* Bucle mientras esperamos
*   Leemos la entrada
*   Si la entrada coincide con 'estoy vivo'
*      Hacemos ...
*   Si la entrada coincide con una trama normal
*      Procesar trama
*   Si la entrada coincide con una de órdenes
*      La almacenamos
*   ...
* Fin bucle


Si no entra en el primer 'if' es quizás porque la $linea leída no corresponde a un 'estoy vivo'. Prueba a pintar la $linea antes de pasar por los 'if' para comprobar realmente qué es lo que llega.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Notapor Josmanue » 2006-10-03 06:03 @294

Acabo de pintar la entrada y es exactamente lo que debe ser, es decir si meto'$SP103' me imprime '$SP103', ya estaba puesto el print pero ponía 'trama' en lugar de 'linea', ya esta bien y eso es lo que sale, pero no entra en el bucle.
En cuanto a lo del esquema no entiendo muy bien lo que me quieres decir, ¿no es asi como lo tengo? lo que pasa es que como le preguntas en el if de las ordenes si la cadena se corresponde con la buscada?
Josmanue
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2006-06-09 04:33 @231

Notapor explorer » 2006-10-03 06:25 @309

Josmanue escribiste:Acabo de pintar la entrada y es exactamente lo que debe ser, es decir si meto'$SP103' me imprime '$SP103', ya estaba puesto el print pero ponía 'trama' en lugar de 'linea', ya esta bien y eso es lo que sale, pero no entra en el bucle.


Prueba a quitar el '$' final de la expresión regular. Es posible que el final de línea tenga más de un carácter.

Josmanue escribiste:En cuanto a lo del esquema no entiendo muy bien lo que me quieres decir, ¿no es asi como lo tengo? lo que pasa es que como le preguntas en el if de las ordenes si la cadena se corresponde con la buscada?


Si, lo tienes así. Pero algunas cosas hay que modificarlas, como el 'next unless...' que hay que trasladar su expresión regular al interior del 'if'. Y sí, dentro de los 'if' deben ir expresiones regulares que coincidan con lo que esperamos. Algo parecido a '/(?:#(1|2)(($campos)+))/', pero personalizado a cada caso.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Josmanue » 2006-10-03 06:48 @325

Ok muchisimas gracias era eso, creo que es que mete un retorno de carro y un salto de linea.
En cuanto al if de las ordenes, si tengo en cuenta la variable '$campos2' creada algo más arriba como el join de los '@campos2' sería esta mi expresion ¿no?
Código: Seleccionar todo
if(($fuente, $trama)=$linea =~/(?:#(1|2)(($campos2)+))/)

Y siguiendo el esquema que seguimos antes para la trama de los partes, ahora tendría que separar la trama en 'campo y valor'
Código: Seleccionar todo
while ( $trama =~/($campos2)/g )
   {
       my ($campo, $valor) = unpack( "A3 A*", $1);
.......
Pero ahora no puedo usar el unpack este ¿no? lo digo por el tema de los caracteres '@' y del campo '@OR' que es de longitud variable.
Josmanue
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2006-06-09 04:33 @231

Notapor explorer » 2006-10-03 10:39 @486

1. Debes repasar si el campo @OT tiene 3 o 5 caracteres. En la trama de muestra pones 3, pero en la expresión regular pones 5.
2. Hay que hacer un pequeño cambio en la expresión regular de los @campos2. Debe ser esta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @campos2 = qw( UID.{5}    FEC.{6}    TIE.{6}    \@OD.{5}    \@OT.{3}    \@OR[^@]+    \@OP. );
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
(sólo hemos quitado un '?').
3. El unpack sigue valiendo porque el nombre de los campos sigue teniendo 3 caracteres de ancho (la '@' cuanta como un carácter más).

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

# #xUIDxxxxxFECxxxxxxTIExxxxxx@ODxxxxx@OTxxx@ORxxxx...@OPx
my @campos2 = qw(
  UID.{5}    FEC.{6}    TIE.{6}    \@OD.{5}    \@OT.{3}    \@OR[^@]+    \@OP.
);

my $campos2 = join('|', @campos2);

my $linea = <>;
chomp $linea;

($fuente, $trama) = $linea =~ /(?:#(0|2)((?:$campos2)+))/;
print "$fuente,$trama\n";

while ( $trama =~/($campos2)/g )
{
    my ($campo, $valor) = unpack( "A3 A*", $1);
    print "\t$campo\t$valor\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Código: Seleccionar todo
explorer@casa:~/Documents/Software/Perl> ./kk.pl
#2UIDSP103FEC123456TIEabcdef@OD12345@OTott@ORordenes@OP1
2,UIDSP103FEC123456TIEabcdef@OD12345@OTott@ORordenes@OP1
        UID     SP103
        FEC     123456
        TIE     abcdef
        @OD     12345
        @OT     ott
        @OR     ordenes
        @OP     1
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Josmanue » 2006-10-03 14:05 @628

El campo '@OT' tiene 3 caracteres, debí confundirme, en cuanto al 'unpack' me alegro un monton de poder usarlo, como llevamos todo el tiempo escapando la '@' creía que me iba a dar problemas. Gracias por la información. Solo hay una cosa que no entiendo, y es que usas esta sentencia:
Código: Seleccionar todo
($fuente, $trama) = $linea =~ /(?:#(1|2)((?:$campos2)+))/;
Y creía que esto ya lo hacía directamente dentro del if:
Código: Seleccionar todo
if(($fuente, $trama)=$linea =~/(?:#(1|2)(($campos2)+))/)
bueno, añadiendo '?:' antes de '$campos2' ¿o es que el 'if' no es así? como no has puesto nada he supesto que estaba bien.
Josmanue
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2006-06-09 04:33 @231

Notapor explorer » 2006-10-03 15:44 @697

Si, es correcto dejarlo dentro del 'if'. Yo sólo he puesto un ejemplo ligeramente distinto para comprobar que funciona. Y sí que hay que poner el '?:' delante de $campos2, aunque... en este caso... da igual...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Josmanue » 2006-10-04 02:43 @155

Pues esto no termina de funcionar aunque supongo que será ya alguna tontería.
Esto es lo que he puesto:

Código: Seleccionar todo
if(($fuente, $trama)=$linea =~/(?:#(1|2)((?:$campos2)+))/)
    {
   print "Fuente:$fuente, $trama\n";
   while ($trama =~/($campos2)/g)
   {
       my ($campo, $valor) = unpack("A3 A*", $1);
       print "\t$campo\t$valor\n";
      
       if ($campo eq 'TIE') { $valor = join(':', $valor =~ /(..)/g) }
       $trama{$campo} = $valor;
      
       my %campos2_bd = (
       UID => 'origen_orden',       FEC => 'dia',           TIE => 'hora',      \@OD => 'destino_orden',
       \@OT => 'tipo_orden',   \@OD => 'orden',     \@OP => 'prioridad',
       );
   }
   my $sql_or ='INSERT INTO ordenes SET ';
   $sql_or   .= join( ', ',
        map  { "$campos2_bd{$_} = \'$trama{$_}\'" }
           grep {      defined $campos2_bd{$_}       }
          keys %trama
       );
   $sql_or   .= ';';

   print " la cadena sql_or tiene: $sql_or\n";
   
   
    }

Y cuando le meto la cadena:
#2UIDSP103FEC061003TIE090000@ODSP105@OTty0@ORGo Home@OP2
esto es lo que me devuelve:
Fuente:2 UIDSP103FEC061003TIE090000@ODSP105@OTty0@ORGo Home@OP2
UID SP103
UID SP103
FEC 061003
TIE 090000
@OD SP105
@OT ty0
@OR Go Home
@OP 2
la cadena sql_or tiene: INSERT INTO ordenes SET ;
Por lo que parece, no coge bien la trama dentro de la sentencia sql y no me la crea bien, ¿sabrías decirme por qué?.
Josmanue
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2006-06-09 04:33 @231

Notapor explorer » 2006-10-04 05:50 @285

Pues que la variable %campos2_bd está definida sólo dentro del bucle while que lee la trama. Luego, al terminar el bucle, esa variable no existe.

Eso te pasa por no usar 'use strict;' :-)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Josmanue » 2006-10-04 06:09 @298

Vale, ya lo he sacado del bucle while y ahora me devuelve esto:
#1UIDSP103FEC061003TIE103000@ODSP105@OTty0@ORGo Home@OP2
Fuente:1, UIDSP103FEC061003TIE103000@ODSP105@OTty0@ORGo Home@OP2
UID SP103
FEC 061003
TIE 103000
@OD SP105
@OT ty0
@OR Go Home
@OP 2
la cadena sql_or tiene: INSERT INTO ordenes SET origen_orden = 'SP103', hora = '10:30:00', dia = '061003';
Sigue sin pillar los campos que empiezan por '@' aunque los separa bien.
No da errores, pero si estos mensajes:
Possible attempt to separate words with commas at ./pfinal.pl line 87.
Name "main::OT" used only once: possible typo at ./pfinal.pl line 142.
Name "main::OP" used only once: possible typo at ./pfinal.pl line 142.
Josmanue
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2006-06-09 04:33 @231

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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