top surveys stackoverflow programming popular most languages development python perl rewrite

python - programming - stackoverflow surveys



Traducir Perl a Python (8)

Encontré este script Perl mientras migraba mi base de datos SQLite a mysql

Me preguntaba (ya que no conozco a Perl) ¿cómo podría uno reescribir esto en Python?

Puntos de bonificación para la respuesta más corta (código) :)

edición : lo siento, quise decir el código más corto, no la respuesta estrictamente más corta

#! /usr/bin/perl while ($line = <>){ if (($line !~ /BEGIN TRANSACTION/) && ($line !~ /COMMIT/) && ($line !~ /sqlite_sequence/) && ($line !~ /CREATE UNIQUE INDEX/)){ if ($line =~ /CREATE TABLE /"([a-z_]*)/"(.*)/){ $name = $1; $sub = $2; $sub =~ s//"//g; #" $line = "DROP TABLE IF EXISTS $name;/nCREATE TABLE IF NOT EXISTS $name$sub/n"; } elsif ($line =~ /INSERT INTO /"([a-z_]*)/"(.*)/){ $line = "INSERT INTO $1$2/n"; $line =~ s//"////"/g; #" $line =~ s//"//'/g; #" }else{ $line =~ s//'/'////'/g; #'' } $line =~ s/([^//'])/'t/'(.)/$1THIS_IS_TRUE$2/g; #'' $line =~ s/THIS_IS_TRUE/1/g; $line =~ s/([^//'])/'f/'(.)/$1THIS_IS_FALSE$2/g; #'' $line =~ s/THIS_IS_FALSE/0/g; $line =~ s/AUTOINCREMENT/AUTO_INCREMENT/g; print $line; } }

Se necesitaba algo de código adicional para migrar con éxito la base de datos sqlite (maneja una línea Crear declaraciones de tablas, claves externas, corrige un error en el programa original que convertía los campos vacíos '''' a /' .

Publiqué el código en la migración de mi base de datos SQLite a mysql Pregunta


Aquí hay una traducción bastante literal con el mínimo de cambios de estilo obvios (poner todo el código en una función, usando cadenas en lugar de operaciones cuando sea posible).

import re, fileinput def main(): for line in fileinput.input(): process = False for nope in (''BEGIN TRANSACTION'',''COMMIT'', ''sqlite_sequence'',''CREATE UNIQUE INDEX''): if nope in line: break else: process = True if not process: continue m = re.search(''CREATE TABLE "([a-z_]*)"(.*)'', line) if m: name, sub = m.groups() line = ''''''DROP TABLE IF EXISTS %(name)s; CREATE TABLE IF NOT EXISTS %(name)s%(sub)s '''''' line = line % dict(name=name, sub=sub) else: m = re.search(''INSERT INTO "([a-z_]*)"(.*)'', line) if m: line = ''INSERT INTO %s%s/n'' % m.groups() line = line.replace(''"'', r''/"'') line = line.replace(''"'', "''") line = re.sub(r"([^''])''t''(.)", r"/1THIS_IS_TRUE/2", line) line = line.replace(''THIS_IS_TRUE'', ''1'') line = re.sub(r"([^''])''f''(.)", r"/1THIS_IS_FALSE/2", line) line = line.replace(''THIS_IS_FALSE'', ''0'') line = line.replace(''AUTOINCREMENT'', ''AUTO_INCREMENT'') print line, main()


Aquí hay una versión ligeramente mejor del original.

#! /usr/bin/perl use strict; use warnings; use 5.010; # for s//K//; while( <> ){ next if m'' BEGIN TRANSACTION | COMMIT | sqlite_sequence | CREATE UNIQUE INDEX ''x; if( my($name,$sub) = m''CREATE TABLE /"([a-z_]*)/"(.*)'' ){ # remove " $sub =~ s//"//g; #" $_ = "DROP TABLE IF EXISTS $name;/nCREATE TABLE IF NOT EXISTS $name$sub/n"; }elsif( /INSERT INTO /"([a-z_]*)/"(.*)/ ){ $_ = "INSERT INTO $1$2/n"; # " => /" s//"////"/g; #" # " => '' s//"//'/g; #" }else{ # '''' => /' s//'/'////'/g; #'' } # ''t'' => 1 s/[^//']/K/'t/'/1/g; #'' # ''f'' => 0 s/[^//']/K/'f/'/0/g; #'' s/AUTOINCREMENT/AUTO_INCREMENT/g; print; }


Basado en http://docs.python.org/dev/howto/regex.html ...

  1. Reemplace $line =~ /.*/ con re.search(r".*", line) .
  2. $line !~ /.*/ es solo !($line =~ /.*/) .
  3. Reemplace $line =~ s/.*/x/g con line=re.sub(r".*", "x", line) .
  4. Reemplace de $1 a $9 dentro de re.sub con /1 a /9 respectivamente.
  5. Fuera de un sub, guarde el valor de retorno, es decir, m=re.search() , y reemplace $1 con el valor de retorno de m.group(1) .
  6. Para "INSERT INTO $1$2/n" específicamente, puede hacer "INSERT INTO %s%s/n" % (m.group(1), m.group(2)) .

El problema real es ¿sabes realmente cómo migrar la base de datos? Lo que se presenta es simplemente un ciclo de búsqueda y reemplazo.


Más corto? La tilde significa un regex en perl. "Importar re" e ir desde allí. Las únicas diferencias clave son que usará / 1 y / 2 en lugar de $ 1 y $ 2 cuando asigne valores, y usará% s para cuando reemplace las coincidencias de expresiones regulares dentro de las cadenas.


No estoy seguro de qué es tan difícil de entender acerca de esto que requiere un comentario sarcástico como en su comentario anterior. Tenga en cuenta que <> se llama el operador de diamante. s/// es el operador de sustitución y // es el operador de coincidencia m// .


Todos los scripts en esta página no pueden tratar con sqlite3 simple:

PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE Filename ( FilenameId INTEGER, Name TEXT DEFAULT '''', PRIMARY KEY(FilenameId) ); INSERT INTO "Filename" VALUES(1,''''); INSERT INTO "Filename" VALUES(2,''bigfile1''); INSERT INTO "Filename" VALUES(3,''%gconf-tree.xml'');

Ninguno pudo reformatear "table_name" en el `table_name` de mysql. Algunos desordenado valor de cadena vacía.


La solución anterior de Alex Martelli funciona bien, pero necesita algunas correcciones y adiciones:

En las líneas que usan la sustitución de expresiones regulares, la inserción de los grupos emparejados debe tener doble escape O la cadena de reemplazo debe tener el prefijo r para marcar es como expresión regular:

line = re.sub(r"([^''])''t''(.)", "//1THIS_IS_TRUE//2", line)

o

line = re.sub(r"([^''])''f''(.)", r"/1THIS_IS_FALSE/2", line)

Además, esta línea debe agregarse antes de imprimir:

line = line.replace(''AUTOINCREMENT'', ''AUTO_INCREMENT'')

Por último, los nombres de columna en las declaraciones de creación deben ser comillas invertidas en MySQL. Agregue esto en la línea 15:

sub = sub.replace(''"'',''`'')

Aquí está el script completo con modificaciones:

import re, fileinput def main(): for line in fileinput.input(): process = False for nope in (''BEGIN TRANSACTION'',''COMMIT'', ''sqlite_sequence'',''CREATE UNIQUE INDEX''): if nope in line: break else: process = True if not process: continue m = re.search(''CREATE TABLE "([a-z_]*)"(.*)'', line) if m: name, sub = m.groups() sub = sub.replace(''"'',''`'') line = ''''''DROP TABLE IF EXISTS %(name)s; CREATE TABLE IF NOT EXISTS %(name)s%(sub)s '''''' line = line % dict(name=name, sub=sub) else: m = re.search(''INSERT INTO "([a-z_]*)"(.*)'', line) if m: line = ''INSERT INTO %s%s/n'' % m.groups() line = line.replace(''"'', r''/"'') line = line.replace(''"'', "''") line = re.sub(r"([^''])''t''(.)", "//1THIS_IS_TRUE//2", line) line = line.replace(''THIS_IS_TRUE'', ''1'') line = re.sub(r"([^''])''f''(.)", "//1THIS_IS_FALSE//2", line) line = line.replace(''THIS_IS_FALSE'', ''0'') line = line.replace(''AUTOINCREMENT'', ''AUTO_INCREMENT'') if re.search(''^CREATE INDEX'', line): line = line.replace(''"'',''`'') print line, main()