• Publicidad

Renombrar campos de tabla a partir de una Base de Datos txt

¿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.

Renombrar campos de tabla a partir de una Base de Datos txt

Notapor Alfumao » 2016-03-14 06:56 @330

Hola a todos.

Tengo un problemilla que no sé muy bien cómo enfocar en el título de este mensaje.

La historia es que tengo una tabla cuyos campos tienen un identificador que modifiqué en su día, y cuyo nombre original guardé en un txt junto a su nuevo nombre en formato:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Nombre_nuevo1 Nombre_antiguo1
Nombre_nuevo2 Nombre_antiguo2
Nombre_nuevo3 Nombre_antiguo3
Nombre_nuevo4 Nombre_antiguo4
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Y así varios miles de registros.

Tras trabajar con estos nombres, tengo una tabla final en la que aparecen solo entradas correspondientes a los nombres nuevos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Nombre_nuevo1 Nombre_nuevo43 Nombre_nuevo17 Nombre_nuevo1245 ...
Nombre_nuevo2 Nombre_nuevo4 Nombre_nuevo37 Nombre_nuevo125 ...
Nombre_nuevo3 Nombre_nuevo51 Nombre_nuevo69 Nombre_nuevo342 ...
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Así pues, he de reemplazar en el mismo archivo (tabla) todos los nombres nuevos por sus correspondientes antiguos (están todos incluidos en el txt que mencioné al principio).

Como no se me ocurría otra forma de hacerlo decidí ejecutar un oneliner para que reemplazase cada Nombre_nuevo por el Nombre_antiguo (no se me ocurre cómo editar el archivo y luego escribirlo una vez hechos todos los reemplazos).

Aquí os dejo el código por sí podéis ayudarme.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2. use strict;
  3. use Getopt::Long;
  4.  
  5. #usage example: perl /storage/Runs/CIC/ANALYSIS/JL_scripts/GetbackIDs.pl -p /storage/... -e txt
  6. #requiere un archivo de secuencias y una "base de datos de IDs" en formato ".txt" que se llamen igual
  7. my ($path, $ext);
  8. GetOptions(
  9.     'path=s'      => \$path,
  10.     'extension=s' => \$ext,
  11.     );
  12.    
  13. print "$path\n";
  14. chdir $path or die "ERROR: Unable to enter $path: $!\n";
  15. opendir (TEMP , ".");
  16. my @files = readdir (TEMP);
  17. closedir TEMP;
  18. print "@files\n";
  19.  
  20. my $name;
  21. my @db;
  22. for my $file (@files) {
  23.     if($file=~/(\w+).$ext/){
  24.         $name = "$1";
  25.         print"This is the Filename: $file\n";
  26.         open (INFILE, "$file") || die ("cannot open input file");
  27.         chomp(my @data = <INFILE>);
  28.         my$file2= "$name.bd";
  29.         print"This is the DBname:$file2\n";
  30.         open (DB, "$file2") || die ("cannot open input file");
  31.         chomp(@db = <DB>);    
  32.     }    
  33. #Reemplazo "on the fly" via One-Liner
  34. for(@db){
  35.         my ($dbid,$firstid) = split(/\t/, $_);
  36.         chomp $firstid;
  37.         print"This is my $dbid and its $firstid\n";
  38.         ##ONELINER #si matchea la id, hacemos cambio
  39.         my$susti=`perl -pi -e 's/$dbid/$firstid/g' $name.$ext`;
  40.         }
  41.     }
Coloreado en 0.007 segundos, usando GeSHi 1.0.8.4


El problema es que parece que se hacen múltiples renombrados uno sobre otro y terminan duplicándose los nombres de varias entradas... Vamos, que el oneliner no funciona correctamente dentro del bucle for (o ese creo yo que debe ser el fallo).

Un saludo.
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Renombrar campos de tabla a partir de una Base de Datos

Notapor Alfumao » 2016-03-14 10:22 @474

Se me olvidaba poner unos ejemplos de los archivos, por si son de utilidad:

"Base de datos" de nombres:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. Aspergillus_clavatus_1  XP_001276684.1 pectate lyase, putative [Aspergillus clavatus NRRL 1]
  2. Aspergillus_fumigatus_2 XP_001276694.1 conserved hypothetical protein [Aspergillus fumigatus NRRL 1]
  3. Aspergillus_flavus_3    XP_001276726.1 tyrosinase central domain protein [Aspergillus flavus NRRL 1]
  4. Aspergillus_terreus_4   XP_001276738.1 endoglucanase, putative [Aspergillus terreus NRRL 1]
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Líneas de la tabla a renombrar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. Aspergillus_clavatus_1  Aspergillus_flavus_198  Aspergillus_terreus_166 Aspergillus_fumigatus_2
  2. Aspergillus_clavatus_1  Aspergillus_flavus_3    Aspergillus_terreus_4   Aspergillus_fumigatus_2
  3. Aspergillus_clavatus_3  Aspergillus_flavus_198  Aspergillus_terreu_166  Aspergillus_fumigatus_16
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Resultado esperado (si el ID a reemplazar no está en la base de datos, no se reemplazaría)
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. XP_001276684.1 pectate lyase, putative [Aspergillus clavatus NRRL 1]    Aspergillus_flavus_198  Aspergillus_terreus_166 XP_001276694.1 conserved hypothetical protein [Aspergillus fumigatus NRRL 1]   
  2. XP_001276684.1 pectate lyase, putative [Aspergillus clavatus NRRL 1]    XP_001276726.1 tyrosinase central domain protein [Aspergillus flavus NRRL 1]    XP_001276738.1 endoglucanase, putative [Aspergillus terreus NRRL 1]     XP_001276694.1 conserved hypothetical protein [Aspergillus fumigatus NRRL 1]
  3. Aspergillus_clavatus_3  Aspergillus_flavus_198  Aspergillus_terreu_166  Aspergillus_fumigatus_16
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Renombrar campos de tabla a partir de una Base de Datos

Notapor explorer » 2016-03-14 17:21 @764

Esta es una posible solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3. use autodie;
  4.  
  5. ## Leer la base de datos
  6. my @cambios;
  7. open my $BASE, '<', 'base_datos.txt';
  8. while (<$BASE>) {
  9.     chomp;
  10.     my($anterior, $nuevo) = split " ", $_, 2;           # partimos la línea en dos cachos
  11.     push @cambios, [ $anterior, $nuevo ];               # y los guardamos en un array de arrays
  12. }
  13. close $BASE;
  14.  
  15. #use Data::Dumper;
  16. #say Dumper \@cambios;
  17.  
  18. ## Procesar los archivos
  19. for my $archivo ('tabla.txt') {                         # por cada archivo
  20.     open my $ARCHIVO, '<',  $archivo;                   # lo abrimos en lectura
  21.     open my $NUEVO,   '>', "$archivo.new";              # abrimos el resultado, en escritura
  22.  
  23.     while (my $linea = <$ARCHIVO>) {                    # por cada línea
  24.         chomp $linea;
  25.        
  26.         for my $cambio_ref (@cambios) {                 # por cada cambio que deseamos hacer
  27.             my($anterior, $nuevo) = @$cambio_ref;
  28.  
  29.             $linea =~ s/\b$anterior\b/$nuevo/g;         # lo hacemos. Atención a los '\b'
  30.         }
  31.  
  32.         say $NUEVO $linea;                              # guardamos el resultado
  33.     }
  34.  
  35.     close $ARCHIVO;
  36.     close $NUEVO;
  37. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Es demasiado sencilla: recorremos todos los cambios por cada línea por cada archivo, lo cual puede eternizarse en caso de que sean muchos archivos o muchas líneas o muchos cambios.

Una forma de optimizarlo es crear una expr. reg. con todas las opciones que buscamos, y mediante un hash, hacer el cambio:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3. use autodie;
  4.  
  5. ## Leer la base de datos
  6. my %cambios;
  7. open my $BASE, '<', 'base_datos.txt';
  8. while (<$BASE>) {
  9.     chomp;
  10.     my($anterior, $nuevo) = split " ", $_, 2;           # partimos la línea en dos cachos
  11.     $cambios{ $anterior } = $nuevo;                     # y los guardamos en un hash
  12. }
  13. close $BASE;
  14.  
  15. ## Creación de la exp. reg.
  16. my $regex = join '|' => keys %cambios;
  17. $regex = qr/\b($regex)\b/;
  18.  
  19. #use Data::Dumper;
  20. #say Dumper \%cambios;
  21.  
  22. ## Procesar los archivos
  23. for my $archivo ('tabla.txt') {                         # por cada archivo
  24.     open my $ARCHIVO, '<',  $archivo;                   # lo abrimos en lectura
  25.     open my $NUEVO,   '>', "$archivo.new";              # abrimos el resultado, en escritura
  26.  
  27.     while (my $linea = <$ARCHIVO>) {                    # por cada línea
  28.  
  29.         $linea =~ s/$regex/$cambios{$1}/g;              # cambiamos lo que encontramos
  30.  
  31.         print $NUEVO $linea;                            # guardamos el resultado
  32.     }
  33.  
  34.     close $ARCHIVO;
  35.     close $NUEVO;
  36. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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

Re: Renombrar campos de tabla a partir de una Base de Datos

Notapor Alfumao » 2016-03-15 09:01 @418

¡Gracias, explorer!

Funciona perfectamente.

Muy interesante el uso de \b en la expresión regular para marcar los límites y evitar solapes en la localización.

;)
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Renombrar campos de tabla a partir de una Base de Datos

Notapor explorer » 2016-03-16 03:48 @200

Pues sí, porque no es lo mismo buscar por

Aspergillus_clavatus_1

que por

Aspergillus_clavatus_11

o

Aspergillus_clavatus_121

Si no fuera por las anclas \b, una clave en %cambios podría solapar sus cambios donde coincidiese primero. Con las anclas, obligamos a buscar conjuntos (palabras) completos. Pero funciona en este problema en particular porque los archivos se componen de elementos separados por espacios o los límites de línea. En otros casos habrá que buscar otro método.
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


Volver a Intermedio

¿Quién está conectado?

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