Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Incorporar texto estructurado a una BD

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Mie Mar 29, 2006 5:17 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Incorporar texto estructurado a una BD Responder citando

Hola, tengo un archivo con la siguiente características:
Código:
1. FN ISI Export Format
2. VR 1.0
3. PT J
4. AU Porras, MD
        Otro, AR
        Y OTRO, OFG
5. TI Three Venezuelan literary journals of the 1960s and the problem of
   culture
6. SO REVISTA IBEROAMERICANA
7. LA Spanish
8. DT Article
9. C1 Univ Simon Bolivar, Caracas 1080, Venezuela.
        Otra Univ Simon Bolivar, Caracas 1080, Venezuela.
        Y OTRA Univ Simon Bolivar, Caracas 1080, Venezuela.
10. RP Porras, MD, Univ Simon Bolivar, Caracas 1080, Venezuela.
11. CR 1958, SARDIO, V1, P1
         1959, SARDIO, V5, P277
         1961, RAYADO TECHO BALLENA
         1961, SARDO, V8, P136
         1963, RAYADO TECHO, V2


Los numero de lineas no vienen, los puse para explicar mejor mi problema.
Las lineas 1 y 2 son un encabezado del archivo descargado, solo aparecen una vez, no son relevantes al menos que se quiera verificar si es o no un registro con la estructura que se espera, para ello hice esto
print "No es un registro ISI" if ($_ =~ m/[1-9]/);
Luego leo cada línea y la meto en un array, el problema surge cuando la línea 4-9-11 tiene más de un elemento (autores) con su respectivo salto de línea. Luego la línea 5 suele estar cortada y el texto continúa en una nueva línea, lo idóneo es que esto todo en una misma línea.
Creé un bucle con if donde extraigo el campo a etiquetar con una expresión regular, quedando así:
Perl:
foreach $campo (@registro)

  {

   if ($campo =~ /^AU:/)

    {

     print "\"$campo\",";

    }

   elsif ($campo =~/^DT:/)

    {

     print "\"$campo\",";

    }

   elsif ($campo =~/^PY:/)

    {

     print "\"$campo\",";

    }

   elsif ($campo =~/^LA:/)

    {

     print "\"$campo\",";

    }

   elsif ($campo =~/^TI:/)

    {


     print "\"$campo\",";

    }

   elsif ($campo =~/^SO:/)

    {

     print "\"$campo\",";

    }

  }

El problema de esto es que si un elemento no existe debería imprimir un mensaje de campo vacío o NULL. Además de no tomar el resto de líneas que mencione antes (4, 9 y 11).
Si me pueden ayudar de antemano, Gracias.
Mensaje Mie Mar 29, 2006 12:27 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4083
Ubicación: Valladolid, España
Responder citando

Yo necesitaría un par de ejemplos...
Mensaje Mie Mar 29, 2006 5:46 pm
kidd
Creador de Perl en Español
Creador de Perl en Español
Registrado: 15 Oct 2003
Mensajes: 1389
Ubicación: México
Responder citando

Hola:

Antes que nada bienvenido al foro.

Tampoco yo termino por comprender exactamente lo que quieres hacer.

Puedes poner un ejemplo del texto original y otro en donde venga ya el resultado que quieres, de esa manera podemos entender un poco lo que quieres quitar o agregar.

También te recomiendo que uses el tag [code] para que podamos diferenciar los pedazos de código.

Saludos
Mensaje Jue Mar 30, 2006 3:31 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Incorporar texto estructurado a una BD Responder citando

Gracias por la bienvenida y las respuestas, Very Happy
Comienzo de nuevo, tengo un archivo de texto con la siguiente estructura:
    FN ISI Export Format
    VR 1.0
    PT J
    AU Porras, MD
    Potras, AD
    Rovero, GK
    TI Three Venezuelan literary journals of the 1960s and the problem of
    culture
    SO REVISTA IBEROAMERICANA
    LA Spanish
    DT Article
    C1 Univ Simon Bolivar, Caracas 1080, Venezuela.
    RP Porras, MD, Univ Simon Bolivar, Caracas 1080, Venezuela.
    CR 1958, SARDIO, V1, P1
    1959, SARDIO, V5, P277
    1961, RAYADO TECHO BALLENA
    1961, SARDO, V8, P136
    1963, RAYADO TECHO, V2
    BELLO AA, 1959, TABLA REDONDA, V4, P4
    NR 21
    TC 0
    PU INST INT LIT IBEROAMERICANA
    PI PITTSBURGH
    PA UNIV PITTSBURGH ATTN: ERIKA BRAGA 1312 CATHEDRAL OF LEARNING,
    PITTSBURGH, PA 15260 USA
    SN 0034-9631
    J9 REV IBEROAMERICANA
    JI Rev. Imberoam.
    PD JUL-DEC
    PY 2004
    VL 70
    IS 208-9
    BP 875
    EP 890
    PG 16
    SC Literature, Romance
    GA 862QM
    UT ISI:000224505900015
    ER

    PT J
    AU Rovero, GK
    Porras, MD
    TI The Latin-American novelist between the Gutemberg galaxy and the
    electronic galaxy - Writers, readers and the "technoperception" of the
    world
    SO HISPAMERICA-REVISTA DE LITERATURA
    LA Spanish
    DT Article
    C1 Univ Simon Bolivar, Caracas 1080, Venezuela.
    Cent Univ Venezuela, Escuela Letras, Caracas, Venezuela.
    RP Rovero, GK, Univ Simon Bolivar, Caracas 1080, Venezuela.
    CR 1991, METAMORFOSIS CULTURA, P174
    BARBERO JM, 1993, REV CRITICA CULTURAL, V7, P20
    BARBERO JM, 1998, MEDIOS MEDIACIONES, P67
    ISER W, 1997, TEORIAS FICCION LIT, P57
    OLAECHEA J, 1986, LIBRO ECOSISTEMA COM, P137
    NR 14
    TC 0
    PU HISPAMERICA
    PI GAITHERSBURG
    PA SAUL SOSNOWSKI 5 PUEBLO COURT, GAITHERSBURG, MD 20878 USA
    SN 0363-0471
    J9 HISPAMERICA-REV LIT
    JI Hispamerica-Rev. Lit.
    PD AUG
    PY 2004
    VL 33
    IS 98
    BP 37
    EP 47
    PG 11
    SC Literature, Romance
    GA 906XD
    UT ISI:000227677200003
    ER


Las dos primera letras en mayúsculas en cada linea determinan el nombre del campo. Cada registro comienza con PT y termina con ER
Los campos AU, TI, C1, RP y CR contienen datos en más de una linea, pero el campo TI (titulo) deberia ir todo en una sola linea.
Lo que necesito hacer es meter cada campo en una base de datos, y que cuando en el archivo no exista un campo en la base de datos se inserte NULL.
Lo primero que se me ocurrio fue meterlo todo en un array, separando cada registro con una barra (|).
Código:
$fichero = 'idb1.txt';
open(INFO, $fichero);
@info=<INFO>;
while (@info)
  {
    @reg=split(/ER-\|/);
    print @reg;
  }

Luego recorrer el array y con if ver si existe cada campo e insertarlo en la BD, con el codigo que puse antes
Código:
foreach $campo (@registro)
{
if ($campo =~ /^AU/)
{
print $campo;
}
elsif ($campo =~/^DT/)
{
print $campo;
}
elsif ($campo =~/^PY/)
{
print $campo;
}
elsif ($campo =~/^LA/)
{
print $campo;
}
elsif ($campo =~/^TI/)
{
print $campo;
}
elsif ($campo =~/^SO/)
{
print $campo;
}
}

Bueno aunque más que un print deberia construir el query para insertar en la BD, eso no lo se hacer.
Los problemas de todo lo anterior es que si un campo tiene más de una linea no recupero esas lineas, y de recuperarlas cada una deberia estar separada por punto y coma(Wink, si un campo no aparece deberia poner NULL porque sino se mueven los valores y no se insertan en el campo que le corresponde. La verdad es que llevo ya un tiempo con esto y no veo la luz al final del tunel, jajaja. Al final deberia quedar algo como esto:
Código:
INSERT INTO TABLA (PT,AU,TI,SO,LA,DT,DE,etc...) VALUES ($PT,$AU,etc..)

pero si por ejemplo $AU no tiene nada, que inserte la palabra NULL o vacio.
Espero haberme explicado un poco mejor, no he estudiado programación y me cuesta explicarme, gracias por las respuestas y paciencia a este novato, gracias. Laughing
Mensaje Jue Mar 30, 2006 3:53 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4083
Ubicación: Valladolid, España
Responder citando

Respuesta rápida. Puedes indicar en la definición de la tabla de la base de datos que, cuando un campo no reciba ningún valor, su valor por defecto sea NULL.
Creo recordar que era algo así como
NOMBRE char(255) default NULL,
Mensaje Jue Mar 30, 2006 5:04 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Responder citando

Ok, gracias por la respuesta. Pero ahora me surge otra duda, si en el sql digo o declaro campo "x" y luego no se le pasa ningun valor, ¿no dara error?
Mensaje Jue Mar 30, 2006 5:48 am
macgregor
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Dic 2004
Mensajes: 117
Ubicación: españa
Responder citando

Hola.
Una posible solución sería crear una variable para cada campo. la puedes declarar como $variable="";
de manera que cuando insertes en la DB si no se ha modificado el valor, se insertará NULL.
Lo delicado es parsear el fichero para asignar cada cosa a una de tus variables. No se si siempre aprecen todos los campos, si además lo hacen en el mismo orden, si cuando es nulo aparecen solo las dos primeras letras que has comentado .....

Respecto a tu ultima pregunta, te dará error dependiendo de como hagas la query.
si haces
Código:
insert into tabla(id_tabla, campo1,campo3,campo4) values (123,$variable1,$variable3,$variable4)
no te dará error a no ser que tu campo 2 no admita nulos, ya que te insertará NULL en este campo.
Si haces
Código:
insert into tabla(id_tabla, campo1,campo2,campo3,campo4) values (123,$variable1,$variable3,$variable4)
está claro que se quejará diciendo que le falta un valor.
Mensaje Jue Mar 30, 2006 7:52 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Responder citando

Efectivamente no siempre aparecen todos los campos, eso si, cuando aparecen mantienen el mismo orden, uno de bajo del otro.
Mensaje Jue Mar 30, 2006 10:09 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4083
Ubicación: Valladolid, España
Responder citando

Bueno, he encontrado una solución.
Código:
1.- Leemos toda la base de datos en una única variable escalar
2.- Por cada registro dentro de esa variable...
3.-  Por cada campo posible...
4.-    Sacamos el valor de ese campo, que esta entre él y el siguiente
5.-  Construímos la query con todos los campos encontrados
Código:
#!/usr/bin/perl

use warnings;
use strict;

# Campos de cada registro
# Nos serviran para buscarles dentro del registro
my @campos = qw(
    AU TI SO LA DT C1 RP CR NR TC
    PU PI PA SN J9 JI PD PY VL IS
    BP EP PG SC GA UT ER
);

# Nombres de los campos de registro en nuestra base de datos
# Nos servirán para meter los valores en los campos de la base de datos
my %campos = (
    AU => 'Autor',       TI => 'Titulo',       SO => 'Organizacion',
    LA => 'Idioma',      DT => 'Tipo',         C1 => 'Copyright',
    RP => 'Propietario', CR => 'Registro',     NR => 'Referencia',
    TC => 'Tomos',       PU => 'Universidad',  PI => 'Ciudad',
    PA => 'Contacto',    SN => 'Serie',        J9 => 'Acronimo',
    JI => 'Acronimo2',   PD => 'Fecha',        PY => 'Año',
    VL => 'Volumen',     IS => 'Tamaño',       BP => 'Indice',
    EP => 'Subindice',   PG => 'Subsubindice', SC => 'Categoria',
    GA => 'IDCategoria', UT => 'ISBN',
);

# Almacen de valores por cada registro
# Aqui guardamos los valores que vamos encontrando en el registro
my %registro;

# Leemos base de datos en texto
my $base = do { local $/; open(BASE,"<kk.txt"); <BASE> };

# Recorremos toda la base por cada registro
while ( $base =~ /(^PT.+?^ER *?$)/smg ) {
    my $registro = $1;
    my %registro = ();

    # Hacemos un bucle por todos los campos posibles
    for(my $i=0; $i<@campos-1;$i++) {

        # Nombre del campo a buscar
        my $campo_actual    = $campos[$i];

        # Buscamos el campo_siguiente que sí exista dentro del registro
        # Esto es necesario porque no sabemos qué campos pueden faltar
        my $campo_siguiente;
        for (my $j=$i+1; $j<@campos; $j++) {
            $campo_siguiente = $campos[$j];
            last if $registro =~ /^$campo_siguiente /sm;
        }

        # Buscamos el contenido del campo.
        # Aquí es donde extraemos el valor del campo, que está entre él y el campo siguiente
        my ($valor) = $registro =~ /^$campo_actual (.+?)^$campo_siguiente */ms;

        # Caso de que no exista... no hacemos nada...
        unless ( defined $valor ) {
            #print "$campo_actual:NULL (no existe)\n";
            next;
        }

        # Quitamos el retorno de carro y ajustamos el título a una sola línea
        chomp $valor;
        if ( $campo_actual eq 'TI' ) {
            $valor =~ s/\n/ /g;
            $valor =~ s/ +/ /g;
        }

        # El campo está vacío, no hacemos nada
        if ( $valor eq '' ) {
            #print "$campo_actual:NULL (vacio)\n";
            next;
        }

        # Si tenemos algo, lo guardamos para luego
        #print "$campo_actual:$valor\n";
        $registro{$campo_actual} = $valor;
    }

    # Después de analizar el registro, confeccionamos la query para la base de datos
    my $query = 'INSERT tabla SET ';

    # Recorremos los campos sacados del registro
    foreach my $campo ( keys %registro ) {
        # Añadimos a la query. El nombre del campo lo sacamos de %campos definido arriba
        $query .= qq( $campos{$campo} = "$registro{$campo}",);
    }

    # Quitamos la última coma y la sustituimos por ;
    substr($query,-1,1) = ';';

    # Ejecutamos la query en la base de datos
    print "$query\n", 'X'x40, "\n";
}

La salida que me sale es:
Código:
INSERT tabla SET  Categoria = "Literature, Romance", Idioma = "Spanish", Autor = "Porras, MD
Potras, AD
Rovero, GK", Tamaño = "208-9", Indice = "875", Universidad = "INST INT LIT IBEROAMERICANA", ISBN = "ISI:000224505900015", Subsubindice = "16", Registro = "1958, SARDIO, V1, P1
1959, SARDIO, V5, P277
1961, RAYADO TECHO BALLENA
1961, SARDO, V8, P136
1963, RAYADO TECHO, V2
BELLO AA, 1959, TABLA REDONDA, V4, P4", Volumen = "70", Copyright = "Univ Simon Bolivar, Caracas 1080, Venezuela.", Acronimo = "REV IBEROAMERICANA", Contacto = "UNIV PITTSBURGH ATTN: ERIKA BRAGA 1312 CATHEDRAL OF LEARNING,
PITTSBURGH, PA 15260 USA", Titulo = "Three Venezuelan literary journals of the 1960s and the problem of culture", Fecha = "JUL-DEC", Propietario = "Porras, MD, Univ Simon Bolivar, Caracas 1080, Venezuela.", Referencia = "21", Subindice = "890", Tipo = "Article", Acronimo2 = "Rev. Imberoam.", Año = "2004", Tomos = "0", Serie = "0034-9631", IDCategoria = "862QM", Organizacion = "REVISTA IBEROAMERICANA", Ciudad = "PITTSBURGH";
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
INSERT tabla SET  Categoria = "Literature, Romance", Idioma = "Spanish", Autor = "Rovero, GK
Porras, MD", Tamaño = "98", Indice = "37", Universidad = "HISPAMERICA", ISBN = "ISI:000227677200003", Subsubindice = "11", Registro = "1991, METAMORFOSIS CULTURA, P174
BARBERO JM, 1993, REV CRITICA CULTURAL, V7, P20
BARBERO JM, 1998, MEDIOS MEDIACIONES, P67
ISER W, 1997, TEORIAS FICCION LIT, P57
OLAECHEA J, 1986, LIBRO ECOSISTEMA COM, P137", Volumen = "33", Copyright = "Univ Simon Bolivar, Caracas 1080, Venezuela.
Cent Univ Venezuela, Escuela Letras, Caracas, Venezuela.", Acronimo = "HISPAMERICA-REV LIT", Contacto = "SAUL SOSNOWSKI 5 PUEBLO COURT, GAITHERSBURG, MD 20878 USA", Titulo = "The Latin-American novelist between the Gutemberg galaxy and the electronic galaxy - Writers, readers and the "technoperception" of the world", Fecha = "AUG", Referencia = "14", Propietario = "Rovero, GK, Univ Simon Bolivar, Caracas 1080, Venezuela.", Subindice = "47", Tipo = "Article", Acronimo2 = "Hispamerica-Rev. Lit.", Año = "2004", Serie = "0363-0471", Tomos = "0", IDCategoria = "906XD", Organizacion = "HISPAMERICA-REVISTA DE LITERATURA", Ciudad = "GAITHERSBURG";
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Un detalle. Si dentro de los campos hay caracteres especiales (comillas), quizás antes haya que pasar el valor por la función quotemeta o alguna otra.

Ultima edición por explorer el Jue Mar 30, 2006 12:52 pm, editado 1 vez
Mensaje Jue Mar 30, 2006 11:39 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Responder citando

Muchisimas gracias a todos y en especial a explorer.
Ahora mismo me pongo a revisarlo y ya comentare impresiones.
Laughing
Mensaje Vie Mar 31, 2006 12:07 pm
kidd
Creador de Perl en Español
Creador de Perl en Español
Registrado: 15 Oct 2003
Mensajes: 1389
Ubicación: México
Responder citando

preiddy escribió:
Ok, gracias por la respuesta. Pero ahora me surge otra duda, si en el sql digo o declaro campo "x" y luego no se le pasa ningun valor, ¿no dara error?


Depende de como declares el campo. Si lo pones que puede ser NULL el valor entonces no hay problema.

Ahora te recomiendo que leas en el manual de MySQL acerca de los campos NULL:
http://dev.mysql.com/doc/refman/4.1/en/problems-with-null.html

Saludos
Mensaje Sab Abr 01, 2006 2:53 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Responder citando

Hola de nuevo, y gracias por las respuestas.
La solución dado por explorer es fenomenal, ahora bien como el objetivo final es aprender tengo unas dudas con el scritp, y claro si pueden ser aclaradas lo agradezco enormemente.
Código:
my $base = do { local $/; open(BASE,"<pubmed-result.txt"); <BASE> };

esta forma de recorrer un archivo es nueva para mi, siempre lo he echo con while, ¿que facilidades o ventajas ofrece hacerlo asi?
Código:
my ($valor) = $registro =~ /^$campo_actual (.+?)^$campo_siguiente */ms;

esta expresión regular me dejo ya fuera, jaja. Pero es el punto fuerte del script, ¿como se extrae el valor?
Si se tiene un archivo de texto con una estructura similar al expuesto en mensajes anteriores, donde cada registro va en una linea, solo con cambiarle los tag seria suficiente para que pueda ser analizado, o eso es lo que creia, pero al hacerlo me imprime algo totalmente diferente a lo que esperaba. El archivo es así:
    PMID- 16571888
    OWN - NLM
    STAT- In-Process
    DA - 20060330
    PUBM- Print
    IS - 1533-4406 (Electronic)
    VI - 354
    IP - 13
    DP - 2006 Mar 30
    TI - Lethal avian influenza A (H5N1) infection in a pregnant woman in Anhui
    Province, China.
    PG - 1421-2
    FAU - Shu, Yuelong
    AU - Shu Y
    FAU - Yu, Hongjie
    AU - Yu H
    FAU - Li, Dexin
    AU - Li D
    LA - eng
    PT - Letter
    PL - United States
    TA - N Engl J Med
    JT - The New England journal of medicine.
    JID - 0255562
    SB - AIM
    SB - IM
    EDAT- 2006/03/31 09:00
    MHDA- 2006/03/31 09:00
    AID - 354/13/1421 [pii]
    AID - 10.1056/NEJMc053524 [doi]
    PST - ppublish
    SO - N Engl J Med. 2006 Mar 30;354(13):1421-2.

    PMID- 16571885
    OWN - NLM
    STAT- In-Process
    DA - 20060330
    PUBM- Print
    IS - 1533-4406 (Electronic)
    VI - 354
    IP - 13
    DP - 2006 Mar 30
    TI - Vaccines against avian influenza--a race against time.
    PG - 1411-3
    FAU - Poland, Gregory A
    AU - Poland GA
    LA - eng
    PT - Comment
    PT - Editorial
    PL - United States
    TA - N Engl J Med
    JT - The New England journal of medicine.
    JID - 0255562
    SB - AIM
    SB - IM
    EDAT- 2006/03/31 09:00
    MHDA- 2006/03/31 09:00
    AID - 354/13/1411 [pii]
    AID - 10.1056/NEJMe068047 [doi]
    PST - ppublish
    SO - N Engl J Med. 2006 Mar 30;354(13):1411-3.

Donde PMID y SO se pueden tomar como inicio y final de campo, hago el respectivo cambio en la linea:
Código:
while ( $base =~ /(^PMID.+?^SO.+?)/smg )

ejectui y esto es lo que imprime:
    INSERT todo SET own = "- NLM
    STAT- In-Process
    DA - 20060330
    PUBM- Print
    IS - 1533-4406 (Electronic)
    VI - 354
    IP - 13
    DP - 2006 Mar 30
    TI - Lethal avian influenza A (H5N1) infection in a pregnant woman in Anhui
    Province, China.", is = " - 1533-4406 (Electronic)
    VI - 354
    IP - 13
    DP - 2006 Mar 30
    TI - Lethal avian influenza A (H5N1) infection in a pregnant woman in Anhui
    Province, China.
    PG - 1421-2
    FAU - Shu, Yuelong
    AU - Shu Y
    FAU - Yu, Hongjie
    AU - Yu H
    FAU - Li, Dexin
    AU - Li D
    LA - eng
    PT - Letter
    PL - United States
    TA - N Engl J Med
    JT - The New England journal of medicine.", dp = " - 2006 Mar 30
    TI - Lethal avian influenza A (H5N1) infection in a pregnant woman in Anhui
    Province, China.
    PG - 1421-2", pt = " - Letter
    PL - United States
    TA - N Engl J Med
    JT - The New England journal of medicine.
    JID - 0255562
    SB - AIM
    SB - IM
    EDAT- 2006/03/31 09:00
    MHDA- 2006/03/31 09:00
    AID - 354/13/1421 [pii]
    AID - 10.1056/NEJMc053524 [doi]
    PST - ppublish", pg = " - 1421-2
    FAU - Shu, Yuelong
    AU - Shu Y
    FAU - Yu, Hongjie
    AU - Yu H
    FAU - Li, Dexin
    AU - Li D
    LA - eng
    PT - Letter", da = " - 20060330
    PUBM- Print
    IS - 1533-4406 (Electronic)
    VI - 354
    IP - 13", pl = " - United States
    TA - N Engl J Med
    JT - The New England journal of medicine.
    JID - 0255562
    SB - AIM
    SB - IM
    EDAT- 2006/03/31 09:00
    MHDA- 2006/03/31 09:00
    AID - 354/13/1421 [pii]
    AID - 10.1056/NEJMc053524 [doi]";
    ########################################

Solo queria ver como lo imprimia, y despues de darle varias vueltas al script para tratar de ajustarlo a este nueva estructura, detecte que esta variante de archivo duplica los tag de los campos cuando tiene más de un valor, es decir, por cada autor le asigna al comienzo el tag AU -. ¿Esa duplicidad de tag puede tener algo que ver con que no reconoce o procesa correctamente el archivo?
Por último y con esto dejo de dar la lata, este nuevo archivo lo puedo obtener en XML, pero con menos datos que uno de txt, ¿existe una libreria de perl que pase directamente del xml a base de datos? porque lo que si he visto es de base de datos a xml.
Bueno de nuevo gracias. Very Happy
Mensaje Sab Abr 01, 2006 5:16 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4083
Ubicación: Valladolid, España
Responder citando

preiddy escribió:
Código:
my $base = do { local $/; open(BASE,"<pubmed-result.txt"); <BASE> };
esta forma de recorrer un archivo es nueva para mi, siempre lo he echo con while, ¿que facilidades o ventajas ofrece hacerlo asi?
Con while es fácil de entender y de usar y es la forma recomendada, ya que a veces trabajamos con ficheros enormes que no caben en memoria, por lo que es normal leer línea a línea y trabajar con cada una.
En el caso de que el fichero sí entre en memoria -y tengamos que trabajar con todo él-, entonces hay varias opciones para leerlo completamente -si ese es nuestro deseo-. Una de ellas es la mostrada: INdefinimos el separador de registros de entrada $/ (por defecto vale lo mismo que un '\n' del sistema) -esto quiere decir que... en realidad el fichero que vamos a leer... NO tiene registros... que es lo mismo que decir que... nos lo vamos a leer todo de una sóla vez-; luego lo abrimos con open y luego lo leemos con '<>'. De esta forma leemos el fichero a una variable e$calar.
Otra forma es esta:
Código:
my @base = do { open(BASE,"<pubmed-result.txt"); <BASE> };
Es casi lo mismo, pero no... aquí abrimos el fichero de forma normal y... ejecutamos la lectura del fichero con '<>'. El operador diamante por defecto funciona en contexto de lista, por lo que devolverá un array con todos los valores (líneas) del fichero, que quedará asignado a nuestra @rray.
How can I read in an entire file all at once? slurp file, slurping.
preiddy escribió:
Código:
my ($valor) = $registro =~ /^$campo_actual (.+?)^$campo_siguiente /ms;
esta expresión regular me dejo ya fuera, jaja. Pero es el punto fuerte del script, ¿como se extrae el valor?
Queda claro que $campo_actual y $campo_siguiente son los campos que estamos buscando -bueno, en realidad queremos lo que está entre los dos-. Cada uno de ellos contienen dos letras en mayúscula.
La expresión regular entonces quiere decir: "Busca (=~) en $registro aquella línea -pues contiene más de una (/m)-, que comienza (^) por nuestro $campo_actual, seguido de un espacio en blanco, seguido por un conjunto de caracteres (.+) -incluído el retorno de carro (/s)-, pero lo menos posible (?) para llegar a la siguiente línea que empieza (^) por el $campo_siguiente seguido de un espacio en blanco. Devuelve el conjunto de caracteres encontrados (()) a la variable $1. Pero como el usuario nos pide un array (($valor)), también lo devolvemos como primer valor de ese array".
preiddy escribió:
Si se tiene un archivo de texto con una estructura similar al expuesto en mensajes anteriores, donde cada registro va en una linea, solo con cambiarle los tag seria suficiente para que pueda ser analizado, o eso es lo que creia, pero al hacerlo me imprime algo totalmente diferente a lo que esperaba.

En el programa que te mandé hay que hacer varios cambios, entonces:
    1.- @campos debe contener los campos que hay dentro del registro Y en el orden en que aparecen
    2.- %campos debe contener la correspondencia de esos campos a los de la base de datos
    3.- En el while, indicar los campos inicio y fin de registro.
preiddy escribió:
Donde PMID y SO se pueden tomar como inicio y final de campo, hago el respectivo cambio en la linea:
Código:
while ( $base =~ /(^PMID.+?^SO.+?)/smg )

ejectui y esto es lo que imprime:
No importa el tamaño de los campos (2 o 4 letras), lo importante es el orden en que están escritos en @campos.
preiddy escribió:
Solo queria ver como lo imprimia, y despues de darle varias vueltas al script para tratar de ajustarlo a este nueva estructura, detecte que esta variante de archivo duplica los tag de los campos cuando tiene más de un valor, es decir, por cada autor le asigna al comienzo el tag AU -. ¿Esa duplicidad de tag puede tener algo que ver con que no reconoce o procesa correctamente el archivo?
Pues sí. El problema es completamente distinto. Si son pocos campos que hacen la duplicidad, entonces hay que plantearlo desde otro punto de vista. Quizás entonces lo más cómodo es volver a recorrer el registro línea a línea e ir almacenando valores con el mismo valor de campo. Luego, sigue igual que antes a la hora de crear la sentencia sql.
preiddy escribió:
Por último y con esto dejo de dar la lata, este nuevo archivo lo puedo obtener en XML, pero con menos datos que uno de txt, ¿existe una libreria de perl que pase directamente del xml a base de datos? porque lo que si he visto es de base de datos a xml.
Diréctamente, creo que no, pero con los módulos XML::Simple y XML::Twig (sobre todo este último) te pueden ayudar bastante.
De todas formas, hay módulos como AnyData::Format::XML que manejan los xml como si fueran bases de datos, por lo que es más fácil aún el pasarles a otra base de datos (incluso no pasarles Smile ).

Actualización: Entra en XML::RDB y busca por 'A Sample Run using MySQL'.
Sí que hay módulos... sólo es cuestión de buscarlos Smile
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group