Сменный / динамический модуль обработки данных / манипулирование / преобразование Perl? - PullRequest
1 голос
/ 17 ноября 2010

Перекрестная публикация от perlmonks:

Мне нужно очистить какой-то грубый, древний код на $ work, и прежде чем я попытаюсь создать новый модуль, я хотел бы использовать существующий, если кто-нибудь знаетчего-то подходящего.

Во время выполнения я анализирую файл, чтобы определить, какую обработку мне нужно выполнить для набора данных.

Если бы я написал модуль, я бы попытался сделать это более обобщенно (не-DBI-специфичный), но мой точный вариант использования таков:

Я читаю файл SQL, чтобы определить запрос для выполнения к базе данных.Я анализирую комментарии вверху и определяю, что

  • столбец A должен иметь как /// примененный,
  • столбец B должен быть преобразован, чтобы выглядеть как дата данного формата,
  • столбец C получает вид tr ///.
  • Кроме того, можно связать цепочку, чтобы столбец D мог ///, а затем сказать, если это не 1 или 2, установитьдо 3.

Так что при извлечении из базы данных программа применяет различные (возможно, суммированные) преобразования перед возвратом данных.

В настоящее время код представляет собой отвратительно большой и сложный рядиз if if обработки ужасно трудно читать или поддерживать массивы инструкций.

Итак, я представляю себе объект, который, возможно, будет анализировать эти строки (и дополнительно предоставлять функциональный интерфейс), составлять список применяемых процессоров, а затем сможет выполнять его на переданном фрагменте.данные.

Опционально может быть опция имени / категории, чтобы один объект мог динамически использоваться для объединения процессоров только для заданного имени / категории / столбца.

Традиционно надуманный пример:

$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"});  

Каждый процессор (gsub, date, exchange) будет отдельной подпрограммой.Плагины могут быть определены, чтобы добавить больше по имени.

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

Итак, первый очевидный вопрос: кто-нибудь знает модуль, который я мог бы использовать?Единственное, что мне удалось найти, это [mod: // Hash :: Transform], но, поскольку я буду определять, какую обработку выполнять динамически во время выполнения, я бы всегда в конечном итоге использовал бы «сложный» вариант, и мне все равно придется собирать парсер / укладчик.

Кто-нибудь знает о каких-либо подобных модулях или даже слегка связанных модулях, которые я мог бы использовать / обернуть?

Если нет ничего общего для общественного потребления (конечно, мой не единственный в темном ящике), есть ли у кого-нибудь какие-либо советы по поводу вещей, о которых следует помнить, или по поводу интерфейсов, и даже по другим возможным причинам, помимо использованиявозврат данных из DBI, Text :: CSV и т. д.?

Если я закончу писать новый модуль, есть ли у кого-нибудь предложения по пространству имен?Я думаю, что что-то в Data ::, вероятно, уместно ... слово «pluggable» приходит на ум, потому что мой пример использования напоминает мне PAM, но у меня действительно нет хороших идей ...

  • Data :: Processor :: Pluggable?
  • Data :: Munging :: Configurable?
  • I :: Chew :: Data?

Ответы [ 3 ]

0 голосов
/ 17 ноября 2010

Мне неизвестны какие-либо модули CPAN для преобразования данных, поэтому мне пришлось свернуть свои собственные для работы.Это было значительно сложнее, чем это, но действовало по аналогичному принципу;в основном это была реализация для ETL в стиле Informatica без необычного графического интерфейса ... конфигурация была хэшей Perl (Perl вместо XML, поскольку она позволяла мне реализовывать некоторые сложные правила в виде ссылок на подпрограммы).

КакЧто касается пространства имен, я бы пошел на Data::Transform::*

0 голосов
/ 07 января 2011

Спасибо всем за их мысли.

Краткая версия: После попытки адаптировать несколько существующих модулей я в итоге абстрагировал свой собственный: Sub :: Chain. Нужно немного поработать, но я делаю то, что мне нужно.

Длинная версия: (выдержка из POD)

= head1 ОБОСНОВАНИЕ

Этот модуль начинался как Data :: Transform :: Named, именованная оболочка (как Sub :: Chain :: Named) вокруг Data :: Transform (и, в частности, Data :: Transform :: Map).

Поскольку модуль был почти готов, я понял, что использую очень мало Data :: Transform (и его документация предполагает, что Я, вероятно, не хотел бы использовать единственную часть, которую я использую). Я также обнаружил, что результат не всегда соответствует ожиданиям. Я решил, что это кажется разумным в соответствии с вероятной целью Data :: Transform, и этот модуль просто должен быть другим.

Поэтому я попытался мыслить более абстрактно и понял, что суть модуля не была привязана к преобразование данных, но только последовательность простых вызовов подпрограмм.

Я тогда нашел и рассмотрел Sub :: Pipeline но нужно было иметь возможность использовать тот же именованная подпрограмма с разными аргументами в одной цепочке, так что мне казалось легче придерживаться кода, который я написал и просто переименуйте его и абстрагируйте его немного дальше.

Я также заглянул в Правило :: Двигатель, который начинал разработку в то время я искал. Однако, как и Data :: Transform, он казался более сложным, чем мне было нужно. Когда я увидел, что Rule :: Engine использует [очень отличный] Moose Я решил пройти, так как я делал работу на нескольких очень старых машинах со старыми дистрибутивами и старыми perls и ограниченными ресурсами. Опять же, казалось, что это намного больше, чем я искал.

= покрой

Что касается метода "разбора" в моей оригинальной идее / примере, Я не нашел это необходимым, и в настоящее время использую синтаксис, такой как

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

0 голосов
/ 17 ноября 2010

Сначала я бы попытался разместить как можно больше форматирования в запросах SQL. Такие вещи, как формат даты и т. Д., Безусловно, должны обрабатываться в SQL.

Вдобавок ко всему, модуль, который я знаю и который можно использовать для вашей цели, это Data :: FormValidator . Несмотря на то, что он в основном предназначен для проверки параметров CGI, он обладает необходимой вам функциональностью: вы можете определять фильтры и ограничения и связывать их различными способами. Это не значит, что для тебя нет других модулей, я просто не знаю.

Или вы можете сделать что-то, на что вы уже намекали. Вы можете определить какие-то классы команд и объединить их в цепочку для различных входных данных. Я бы сделал что-то вроде этого:

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