Pregunta

Cruz-registrado desde perlmonks:

Tengo que limpiar algo de código bruto, antigua en $ trabajo, y antes de tratar de hacer un nuevo módulo Me encantaría usar una existente si alguien sabe de algo apropiado.

En tiempo de ejecución Estoy análisis de un archivo para determinar lo que el procesamiento que necesito hacer en un conjunto de datos.

Si tuviera que escribir un módulo me gustaría tratar de hacerlo de manera más genérica (no-DBI-específico), pero mi caso de uso exacta es la siguiente:

Leo un archivo SQL para determinar la consulta se ejecute en contra de la base de datos. I comentarios de análisis sintáctico en la parte superior y determinar que

     
  • necesidades columna A para tener una s /// aplicada,
  •  
  • necesidades de la columna B para ser transformados para parecer una fecha de formato dado,
  •  
  • columna C consigue un tipo de tr ///.
  •  
  • Además cosas se pueden encadenar de manera ///, y luego decir que la columna D podría s si no es 1 ó 2, ponerlo a 3.

Así que cuando ir a buscar desde el PP se aplica el programa de las diversas transformaciones (posiblemente apilados) antes de regresar los datos.

Actualmente el código es una serie desagradablemente grandes y difíciles de si las cláusulas procesamiento terriblemente difícil de leer o mantener conjuntos de instrucciones.

Así que lo que estoy imaginando tal vez sea un objeto que va a analizar esas líneas (Y adicionalmente exponer una interfaz funcional), apilar hasta la lista de procesadores de aplicar, a continuación, ser capaz de ejecutar en un pedazo pasado de los datos.

Opcionalmente puede haber una opción de Nombre / categoría, de modo que un objeto se podría utilizar de forma dinámica para apilar los transformadores por el nombre / categoría / columna dada.

Un ejemplo tradicionalmente ideado:

$obj = $module->new();  
$obj->parse("-- greeting:gsub: /hi/hello"); # don't say "hi"  
$obj->parse("-- numbers:gsub: /\D//"); # digits only  
$obj->parse("-- numbers:exchange: 1,2,3 one,two,three"); # then spell out the numbers  
$obj->parse("-- when:date: %Y-%m-%d 08:00:00"); # format like a date, force to 8am  
$obj->stack(action => 'gsub', name => 'when', format => '/1995/1996/'); # my company does not recognize the year 1995.  

$cleaned = $obj->apply({greeting => "good morning", numbers => "t2", when => "2010116"});  

Cada procesador (gsub, fecha, intercambio) sería una subrutina separada. Plugins podrían definirse para añadir más por su nombre.

$obj->define("chew", \&CookieMonster::chew);  
$obj->parse("column:chew: 3x"); # chew the column 3 times  

Así que la primera pregunta obvia es, ¿alguien sabe de un módulo por ahí que podría utilizar? Sobre lo único que era capaz de encontrar hasta ahora es [mod: // Hash :: Transformar], pero ya que sería determinante que el procesamiento que se puede hacer dinámicamente en tiempo de ejecución Lo haría siempre terminar con el opción "complejo" y todavía tendría que construir el analizador / apilador.

¿Hay alguien al tanto de cualquier módulos similares o incluso un módulo ligeramente relacionado que puede ser que quiera utilizar / envoltura?

Si no hay nada fuera genérica no para el consumo público (seguramente el mío no es el único en el darkpan), ¿Alguien tiene algún consejo para las cosas a tener en mente o interfaz sugerencias o incluso otros usos posibles Además munging el retorno de datos de DBI, Texto :: CSV, etc?

Si termino de escribir un nuevo módulo, ¿Alguien tiene sugerencias de espacio de nombres? Creo que algo bajo de datos :: es probablemente adecuada ... la palabra "enchufable" sigue viniendo a la mente porque mi caso de uso me recuerda PAM, pero realmente no tengo ninguna idea buena ...

     
  • Datos :: Procesador :: enchufable?
  •  
  • Datos :: :: Munging configurable?
  •  
  • I :: :: Chew datos?
¿Fue útil?

Solución 3

Gracias a todos por sus pensamientos.

La versión corta: Después de tratar de adaptar unos módulos existentes que terminé mi propia abstracción: Sub :: cadena. Se necesita algo de trabajo, pero está haciendo lo que necesito hasta el momento.

La versión larga: (Un extracto de la POD)

= head1 FUNDAMENTO

Este módulo comenzó como datos :: :: Transformar Nombre, una envoltura llamada (como Sub :: :: Cadena Named) alrededor Datos :: Transform (y en concreto de datos :: :: Mapa Transformar).

A medida que el módulo fue casi terminado me di cuenta de que estaba usando muy poco de datos :: Transform (y su documentación sugiere que Lo que probablemente no quiera usar la única parte que me he usando). También encontré que la salida no siempre fue lo que esperaba. Decidí que parecía razonable de acuerdo a la finalidad probable de datos :: Transformar y este módulo, simplemente tenía que ser diferente.

Así que he tratado de pensar de manera más abstracta y se dio cuenta de que la esencia del módulo no estaba atado a transformación de datos, sino que simplemente la sucesión de llamadas a subrutinas simples.

Entonces encontró y considera Sub :: Pipeline pero necesaria para poder utilizar el mismo llamado subrutina con argumentos diferentes en una única cadena, por lo que parecía más fácil para mí para seguir con el código que había escrito y acaba de cambiar su nombre y abstracta que sea un poco más lejos.

También se veía en la Regla :: motor que comenzaba el desarrollo en el momento que estaba buscando. Sin embargo, al igual que datos :: Transform, parecía más complejo que lo que necesitaba. Cuando vi que la Regla :: motor estaba usando [el excelente] Moose Decidí pasar desde que estaba haciendo el trabajo en un número de máquinas muy antiguas con distribuciones de edad y perlas viejas y recursos limitados. Una vez más, parecía que era mucho más de lo que estaba buscando.

= corte

En cuanto al método "de análisis" en mi idea original / ejemplo, No he encontrado que sea necesario, y actualmente estoy usando una sintaxis como

$chain->append($sub, \@arguments, \%options)

Otros consejos

En primer lugar me gustaría tratar de colocar la mayor cantidad de formateo como sea posible en las consultas SQL, si es posible. Cosas como el formato de fecha, etc. Sin duda deben ser manejados en SQL.

Sale superior de mi cabeza un módulo que sé y que podría ser utilizado para su propósito es datos :: FormValidator . Aunque es tiene como objetivo principal la validación de parámetros CGI, tiene la funcionalidad que necesita: puede definido filtros y limitaciones y encadenarlos de varias maneras. No significa que no hay otros módulos para que propósito, simplemente no lo saben.

O usted puede hacer algo de lo que ya se ha insinuado en. Se podría definir algún tipo de clases de órdenes y los de la cadena en las diversas entradas de datos. Me gustaría hacer algo en este sentido:

package MyDataProcessor;

use Moose;
has 'Transformations' => (
    traits => ['Array'],
    is => 'rw',
    isa => 'ArrayRef[MyTransformer]',
    handles => {
        add_transformer => 'push',
    }
);

has 'input' => (is => 'rw', isa => 'Str');

sub apply_transforms {  }


package MyRegexTransformer;

use Moose;

extends 'MyTransformer';

has 'Regex' => (is => 'rw', isa => 'Str');
has 'Replacement' => (is => 'rw', isa => 'Str');

sub transform {  }

# some other transformers
#

# somewhere else
#
#

my $processor = MyDataProcessor->new(input => 'Hello transform me');

my $tr = MyRegexTransformer->new(Regex => 'Hello', Replacement => 'Hi');

$processor->add_transformer($tr);

#...

$processor->apply_transforms;

No estoy enterado de ninguna información transformar los módulos de CPAN, por lo que he tenido que rodar mi propio trabajo. Fue significativamente más complicado que esto, pero opera bajo un principio similar; que era básicamente la implementación de un hombre pobre de estilo Informatica sans ETL la GUI de fantasía ... la configuración era hash de Perl (Perl en lugar de XML, ya que me permitió implementar ciertas reglas complejas como las referencias a subrutinas).

En cuanto a espacio de nombres, me gustaría ir a Data::Transform::*

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top