• Publicidad

Formatear string

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Formatear string

Notapor xchidalgox » 2007-04-02 11:59 @541

Hola.

Necesito ayuda para formatear una cadena. por ejemplo

#ID (largo 1)
#Nombre(largo 5)
#Apellido(largo 10)
#Telefono(largo 6)
#Edad (largo 2)
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$var   ='1Pedro Perez      23232956';
$var1  ='1Jaime Perez      28732956';
$var2  ='1SergioPerez      26732956';
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


El tamaño de las columas es fija.

Me piden que separe con * la columna 1,5 (nombre) y 18,23 (teléfono),siempre me piden por posiciones, entonces debería quedar así:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$var_format   = '1*Pedro *Perez      *232329*56';
$var1_format  = '1*Jaime *Perez      *287329*56';
$var2_fotmar  = '1*Sergio*Perez      *267329*56';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Cualquier sugerencia es bienvenida.

Saludos.
xchidalgox
Perlero nuevo
Perlero nuevo
 
Mensajes: 23
Registrado: 2007-04-02 11:23 @516

Publicidad

Notapor explorer » 2007-04-02 15:59 @707

Bienvenido a los foros de Perl en Español.

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

@x = (
    '1Pedro Perez      23232956',
    '1Jaime Perez      28732956',
    '1SergioPerez      26732956',
);

for my $linea ( @x ) {
    for my $i ( 24, 18, 7, 1 ) {
        substr $linea, $i, 0, '*';
    }
    print "$linea\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Se utiliza la técnica de ir insertando los '*' usando la función substr en modo 'cuatro argumentos'.

La posición de los caracteres la vamos haciendo de atrás hacia adelante, porque cada vez que insertamos un carácter, cambian las posiciones de todos los caracteres que le siguen (la cadena de caracteres va creciendo).
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

formatear string

Notapor xchidalgox » 2007-04-03 09:34 @440

Hola,

La idea es que las posiciones sean ingresados por parametros, por ejemplo para insertar * de 1,5 las posisiones cambian de 1,7 o sea suma 2 y despues suma 1 18,23 a 18,24.

Hay mas variantes si las posiciones esta en columnas juntas tambien cambia la forma de incrementar. 1,5 y 6,15 (nombre y el apellido) como el * final de nombre
es el * inicial de apellido, los incrementos varian.

El algoritmo generico y optimo es lo que estoy tratando de conseguir.

Saludos
xchidalgox
Perlero nuevo
Perlero nuevo
 
Mensajes: 23
Registrado: 2007-04-02 11:23 @516

Notapor explorer » 2007-04-03 10:20 @472

Pues ahora sí que me he perdido... no lo acabo de entender...
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

formatear string

Notapor xchidalgox » 2007-04-03 14:00 @625

espero explicarme esta vez......

la respuesta que me diste era para el caso particualar de las posiciones 1,5 y 18,23 entonces este codigo funciona.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for my $i ( 24, 18, 7, 1 ) {
        substr $linea, $i, 0, '*';
    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Lo que hiciste fue sumar 2 a la segunda cordenada de la primera posicion y sumar 1 a la segunda coordenada de la seguna posicion. (1,5+2) (18,23+1), pero no es siempre asi (sumar 2 luego sumar 1)

Si las posiciones son otras el algoritmo obviamente no funciona, entonces lo que necesito es un algoritmo generico, para cualquier posicion.
xchidalgox
Perlero nuevo
Perlero nuevo
 
Mensajes: 23
Registrado: 2007-04-02 11:23 @516

Notapor creating021 » 2007-04-03 14:24 @641

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/env perl
use strict;
my @x = (
    '1Pedro Perez      23232956',
    '1Jaime Perez      28732956',
    '1SergioPerez      26732956',
);

my @out;

foreach (@x){
  my ($id, $nom, $ape, $tel, $ed) = unpack("A1A6A11A6A2", $_);
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Con eso tienes :wink:

PD: Los teléfonos tienen 7 números (al menos aquí)
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor explorer » 2007-04-03 17:18 @763

Si le sumé 1 y 2 es porque no coincide el ejemplo con tus especificaciones: Sergio tiene 6 letras, no 5. Y el campo de apellido se ve que son 11 caracteres, no 10.

Y lo que no entiendo es lo que significan las coordenadas 1,5.

¿1 significa primer campo, o la posición del '*' dentro de la línea? ¿5 qué significa? ¿La longitud de ese campo? ¿1,5 significa que hay que poner el '*' en el primer campo pasados 5 caracteres? ¿No sabemos el tamaño de los campos al principio? ¿O es que 1,5,18 y 23 son justo las posiciones donde hay que poner los '*'?

Por otra parte, ¿cómo nos dan las coordenadas? ¿Por la línea de argumentos, en un fichero externo o por la entrada estándar?
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

formatear string

Notapor xchidalgox » 2007-04-03 18:09 @798

Tienes razón, me equivoqué en el número de caracteres era 6 y no 5 y era 11 no 10. Disculpa.

Explico.

Las posiciones se pasan por parámetros al ejecutar el script.

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
# perl separar.pl 1,6 7,17
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Esto quiere decir que hay que separar entre * el dato que esta en la posición 1,6 y 7,17 (Fíjate que digo el dato, y no nombre y apellido, porque desconozco la información que hay en la línea) . No conozco todo el formato de la línea, por ejemplo no sé que las siguientes 6 posiciones después del apellido corresponden al teléfono las 2 siguientes a la edad, solo conozco las que me pasan por parámetros y si me las pasan es porque hay un dato relevante.

Código: Seleccionar todo
1Pedro Perez      23232956


Código: Seleccionar todo
según la línea anterior 1,6 es exactamente 'Pedro ' y 7,17 es 'Perez      ' por lo tanto la línea con * debe quedar así

1*Pedro *Perez      *23232956


Las posiciones que pasan por parámetros son las posiciones donde hay una data y esa data hay que dejarla entre *.

El ejemplo que tu me das no me sirve del todo ya que no me guarda el dato con los espacios que tiene originalmente.
Ademas no se en cuantas variables tengo que dejarlo porque me pueden pasar un número ilimitado de posiciones, dependiendo del largo de la cadena y qué datas quieren separar entre *.

Espero haberme explicado con claridad, si no es así dímelo nuevamente.

Gracias por tu ayuda.

Saludos
xchidalgox
Perlero nuevo
Perlero nuevo
 
Mensajes: 23
Registrado: 2007-04-02 11:23 @516

Notapor creating021 » 2007-04-03 19:20 @847

Por eso, mira el código que he pusto, es fácil de modificar para eso.

Mi código te sepera cada cosa (según tus especificaciones) y solo tendras que identificar que es lo que se está pidiendo.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor explorer » 2007-04-03 19:37 @859

Bueno, he encontrado una solución.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -l

@lineas = (
    '1Pedro Perez      23232956',
    '1Jaime Perez      28732956',
    '1SergioPerez      26732956',
);

# Leemos los argumentos
my @pos;
for my $pos ( @ARGV ) {
    my ($primera,$ultima) = split q{,}, $pos;
    push @pos, $primera;
    push @pos, $ultima+1;       # Aquí está el primer truco
}

# Ordenación de las posiciones, en orden inverso
@pos = sort { $b <=> $a } @pos;
print "@pos";

# Para todas las líneas...
for my $linea ( @lineas ) {

    my $pos_ant = 0;            # Recordaremos la última posición

    # Para todas las posiciones...
    for my $pos ( @pos ) {
        next if $pos == $pos_ant;       # No la tenemos en cuenta si ya la pusimos antes

        substr($linea,$pos,0) = '*';    # Colocamos el punto peludo

        $pos_ant = $pos;                # Recuerda...
    }

    print "$linea";
}
__OUT__
> ./separar.pl 1,6 7,17
18 7 7 1
1*Pedro *Perez      *23232956
1*Jaime *Perez      *28732956
1*Sergio*Perez      *26732956
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La estrategia es la siguiente:
1. Consideramos que todas las coordenadas que nos pasan están basadas en 0.
2. Las coordenadas que nos indican, separadas por una coma, van del carácter inicial al final del campo a separar. En una situación normal, usando el substr() como en los ejemplos anteriores, no hay problema en usar la coordenada inicial (pues está sobre el primer carácter del campo), pero sí en la coordenada final. No podemos colocar allí el asterisco, sino en la posición siguiente (el asterisco debe rodear el campo, colocándose delante del primer carácter del siguiente campo). Por eso le sumamos 1 en la coordenada final.
3. Ordenamos las coordenadas de forma numérica y al revés, para evitar los mismos problemas que comentamos en los primeros mensajes: es mejor que el string vaya creciendo desde el final hasta el principio para no tener que hacer cuentas de desplazamiento de coordenadas.
4. La única preocupación que queda a la hora de colocar los asteriscos es ver si vamos a colocar un asterisco dos veces en el mismo sitio. Por eso usamos una variable que nos recuerda la última posición puesta. Si es igual a la actual, pasamos a la siguiente.

De esta forma, incluso se tienen en cuenta otros casos extremos:
a. Coordenadas repetidas:
perl separar.pl 1,6 1,6
1*Pedro *Perez 23232956

b. Coordenadas desordenadas:
perl separar 7,17 1,6
1*Pedro *Perez *23232956

c. Coordenadas con rangos comunes:
perl separar 1,6 3,17
1*Pe*dro *Perez *23232956

Incluso substr es lo bastante inteligente como para poner un asterisco al final de la cadena, pero no más allá.
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 Intermedio

¿Quién está conectado?

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

cron