2016-11-01 4 views
1

私は下の例のような設定ファイルを変換しようとしているので、Oracleのテーブルに挿入するSQLコマンドを生成できます。私はPerlを使ってみようとしていますが、私はPythonのような他の言語を試してみたいと思っています。設定の複雑な設定ファイルをid、parent、key、valueの形式に変換する

例:(スペースはちょうどより見やすくするためのものである)に変換

# This is a comment 
feed_realtime_processor_pool = (11, 12) ; 
dropout_detection_time_start = "17:00"; 
# Sometimes the config can have sub-structures 
named_clients = (
{ 
    name = "thread1"; 
    user_threads = (
    { name = "realtime1"; cpu = 11; } # more comments 
    { name = "realtime2"; cpu = 12; } # more comments 
    ); 
} 
); 

(...)

id,parent, key,       value 
01,null, 'feed_realtime_processor_pool', '11' 
02,null, 'feed_realtime_processor_pool', '12' 
03,null, 'dropout_detection_time_start', '17:00' 
04,null, 'named_clients',    null 
05,04,  'name',       'thread1' 
06,04,  'user_threads',     null 
07,06,  'name',       'realtime1' 
08,06,  'cpu',       '11' 
09,06,  'name',       'realtime2' 
10,06,  'cpu',       '12' 

ので、ご質問は以下のとおりです。

  1. Somebo dyはこれを行うことができるいくつかのlib /モジュールを知っていますか?私はconfigパーサを見つけることができましたが、ツリー形式で私に与える良いものを見つけることができませんでした。

  2. もしそうでなければ、私はこのスクリプトをどのように起動するべきか、誰かが私に設定を解析するのに役立つ別のモジュールを使用するべきかについていくつかの示唆を与えることができますか?設定のクリーニングと解析は私の最も難しい部分です。

まずアップデート:私は言及を忘れてしまった

  1. 、私は私のデータベースにインポートするコンフィグのトンを持っており、これは1回限りのイベントではありません。このスクリプトは、別のインストールのために私の会社の顧客によって生成された新しい設定があるたびに実行されます。
  2. これはPythonが実行するよりも速いと思っていたので、私はperlを選択しました。
  3. 私は非常にSQLに精通していますが、Perlをあまりよく使っていません
  4. configsは、私が例を挙げたのと同じ構造に従いますが、唯一のバリエーションはキー/値のペアまたは中括弧の字下げなどがあります。
  5. DBIを使用してperlスクリプトを作成し始めましたが、主な問題はこの設定を簡単に処理できる形式に解析することです。私は正規表現が壊れている状況を常に見つけており、何度も何度も調整を続けています。自動的に設定を解析するためにlibを使うことができれば、それは素晴らしいことです。私はあなたが言及したものを試してみるつもりです。

ありがとう!

2回目の更新:

Guysは、私はPerl Monksでこの質問をクロスポストと私もテストしてることがある別のフィードバックを得ました。私はすべてをテストしたら回答を投稿します。ありがとう。

+0

良い点は、私が今より多くの情報を追加しました。ありがとう –

+0

[クロスポスト](http://perlmonks.org/?node_id=1175079) – stevieb

答えて

2

おかげさまで皆様にお礼を言いますが、最良の選択肢は、perlmonksサイトのChorobaから受け取った提案に従うことだと思います。私は彼の答えをここにコピーしています:

"あなたの設定フォーマットを解析するモジュールが見つからない場合は、あなた自身のパーサーを書いてください。Marpa :: R2は、タスクのお手伝いをすることができます:

#!/usr/bin/perl 
use warnings; 
use strict; 
use feature qw{ say }; 

use Marpa::R2; 

my $input = << '__INPUT__'; 
# This is a comment 
feed_realtime_processor_pool = (11, 12) ; 
dropout_detection_time_start = "17:00"; 
# Sometimes the config can have sub-structures 
named_clients = (
{ 
    name = "thread1"; 
    user_threads = (
    { name = "realtime1"; cpu = 11; } # more comments 
    { name = "realtime2"; cpu = 12; } # more comments 
    ); 
} 
); 
__INPUT__ 

my $dsl = << '__DSL__'; 

lexeme default = latm => 1 
:default ::= action => ::first 

Config ::= Elements 
Elements ::= Element+        action => grep_def 
+ined 
Element ::= (Comment)        action => empty 
      | Name (s eq s) Value     action => [values] 
      | Name (s eq s) Value (semicolon s)  action => [values] 
Comment ::= (hash nonnl nl)      action => empty 
Name  ::= alpha 
Value  ::= List 
      | String 
      | Num 
      | Struct 
List  ::= (lpar) Nums (rpar s semicolon s) 
Nums  ::= Num+ separator => comma    action => listify 
Num  ::= (s) digits (s) 
      | (s) digits 
      | digits (s) 
      | digits 
String ::= (qq) nqq (qq semicolon s)    action => quote 
Struct ::= (lpar s) InStructs (rpar semicolon s) 
InStructs ::= InStruct+        action => grep_def 
+ined 
InStruct ::= (lcurl s) Elements (rcurl s) 
      | (Comment s)       action => empty 
      | Element 

s   ~ [\s]* 
eq  ~ '=' 
hash  ~ '#' 
nonnl  ~ [^\n]* 
nl  ~ [\n] 
alpha  ~ [a-z_]+ 
lpar  ~ '(' 
rpar  ~ ')' 
lcurl  ~ '{' 
rcurl  ~ '}' 
semicolon ~ ';' 
comma  ~ ',' 
digits ~ [\d]+ 
qq  ~ '"' 
nqq  ~ [^"]+ 

__DSL__ 

sub listify  { shift; [ @_ ] } 
sub quote  { qq("$_[1]") } 
sub empty  {} 
sub grep_defined { shift; [ grep defined, @_ ] } 


my $id = 1; 
sub show { 
    my ($parent, $name, $elems) = @_; 
    if (ref $elems->[0]) { 
     show($parent, $name, $_) for @$elems; 
    } elsif (ref $elems->[1]) { 
     if (ref $elems->[1][0]) { 
      say join ', ', $id, $parent, $elems->[0], 'null'; 
      show($id++, $elems->[0], $elems->[1]); 
     } else { 
      for my $e (@{ $elems->[1] }) { 
       say join ', ', $id++, $parent, $elems->[0], $e; 
      } 
     } 
    } else { 
     say join ', ', $id++, $parent, @$elems; 
    } 
} 


my $grammar = 'Marpa::R2::Scanless::G'->new({ source => \$dsl }); 
show('null', q(), ${ $grammar->parse(\$input, 'main') }); 
[download] 
Output: 

1, null, feed_realtime_processor_pool, 11 
2, null, feed_realtime_processor_pool, 12 
3, null, dropout_detection_time_start, "17:00" 
4, null, named_clients, null 
5, 4, name, "thread1" 
6, 4, user_threads, null 
7, 6, name, "realtime1" 
8, 6, cpu, 11 
9, 6, name, "realtime2" 
10, 6, cpu, 12 

は、このモジュールをインストールすることに注意してください、私たちは多くの依存関係をインストールする必要があります。

sudo cpan IPC::Cmd 
sudo cpan Module::Build 
sudo cpan Time::Piece 
sudo cpan Marpa::R2 
+0

perlmonksからの回答をこちらに投稿していただき、ありがとうございます。[@Choroba](http://stackoverflow.com/users/1030675/choroba)記録のためだけに:彼はまた、このサイトのメンバーです。そして、もし私がそれを言えば、素晴らしい人です。 :-) – PerlDuck

+0

ああ、それは、ええ、彼は本当に素晴らしいと知りませんでした。 :-) –

1

Perlが設定ファイルを分解してそこからSQL文を作成するように思えますが、そのようにすることはIDを作成することを意味し、データベースが自動インクリメントすると問題を引き起こす可能性があります。

Perlを使って直接データベースと対話する方法を学ぶことをお勧めします。この領域は、DBIDBIx::Classの2つのモジュールによって支配されています。

両方のモジュールは、データの作成、読み取り、更新、削除のためのメソッドを提供し、後続のクエリでIDや他のテーブルデータを使用できるようにクエリからの戻り値を格納できます。彼らはまた、常に良いトランザクションのエラー処理があります。

これは単発のスクリプトであり、すでにSQLに精通しているので、多くの一般的なSQLを使用しており、学習するのが早いためDBIをお勧めします。

OOソリューションでPerlでデータベースを使用したい場合や、多くのデータベース作業を行う場合は、DBIx :: Classを学ぶことをお勧めします。より堅牢なソリューションのためのスキーマ。

どちらの場合でも、DBIとDBIx :: ClassのルールがOracleデータベースと対話する必要があるDBD::Oracleモジュールが必要です。

更新:

私が言及するのを忘れてしまった...あなたはSQL文に、configファイルの変換について断固としている場合は、SQL文の中でPerlのデータ構造を変換SQL::Abstractを試みることができます。

アップデート2:

私はその具体的な設定構文のためのモジュールがありますかどうかわからないんだけど、それはJSONの形式にかなり近い見えますので、あなたはそれにファイルを変換し、その後でそれらを読み込むことができますJSON

コメントを削除する必要があります。配列をかっこから角括弧に変更し、等号をコロンに変更し、すべてのテキストを引用符で囲む必要があり、セミコロンをカンマに変更する必要があります。最も難しいのは、各ブロックから最後のカンマを削除することだと思います。

は、末尾のカンマを削除するに捕まってしまったが、これはあなたが道のほとんどを取得する必要があります。

my $config = <<'CONFIG'; 
# This is a comment 
feed_realtime_processor_pool = (11, 12) ; 
dropout_detection_time_start = "17:00"; 
# Sometimes the config can have sub-structures 
named_clients = (
{ 
    name = "thread1"; 
    user_threads = (
    { name = "realtime1"; cpu = 11; } # more comments 
    { name = "realtime2"; cpu = 12; } # more comments 
    ); 
} 
); 
CONFIG 

# Remove comments 
$config =~ s{[#].+?$}{}mg; 

# Convert Arrays 
$config =~ s{\(}{[}mg; 
$config =~ s{\)}{]}mg; 

# Convert key-value seaprators 
$config =~ s{=}{:}mg; 

# Wrap text in quotes 
$config =~ s{"?([\w\d]+)"?}{"$1"}mg; 
$config =~ s{"(\d\d?)":"(\d\d?)"}{"$1:$2"}mg; # fix times 

# Convert eol delimiters 
$config =~ s{;}{,}mg; 



# Wrap whole thing in brackets 
$config = '{' . $config . '}'; 

print "$config\n\n"; 
+0

面白い... SQL :: Abstractを試してみましょう。しかし、configファイルをPerlのデータ構造に解析することができるlibを知っていますか? –

+0

JSON構文に変換し、[JSON](https://metacpan.org/pod/JSON)モジュールを使用してみてください。あなたがする必要があるのは、カッコ、等号、セミコロンを変換して引用符で囲んだテキストなので、次のようになります。 – interduo

+0

erm、コメントにコードを追加しても機能しませんでした。 – interduo

1

はさておきオラクルを置く、あなたは以来、Pythonであなたの「設定」ファイルで何かを行うことができるかもしれません互換性がない場合、その構文は似ています(私はあなたにそれを伝えることはできません)。しかし、私はPerlで評価する何かを認識していません。

feed_realtime_processor_pool 11 
feed_realtime_processor_pool 12 
dropout_detection_time_start 17:00 
# Sometimes the config can have sub-structures 
<named_client thread1> 
    <user_threads realtime1> 
    cpu 11 
    </user_threads> 
    <user_threads realtime2> 
    cpu 12 
    </user_threads> 
</named_client> 

# etc 

し、それをお読みください:代わりに、あなたはこのようになります設定ファイルを許可することになるコンフィグ::全般を試みることができる

use Config::General; 
$config = Config::General->new("my.conf"); 
my %config = $config->getall; 

より単純な選択肢がuse JSONまたはXMLとJSONかもしれません:: SimpleはCPANでそれらをチェックしてください。これらは、おなじみの構文でツリーフォーマットを提供します。

+0

おかげで、あなたの提案も同様に試みます。私がアップデートを入れたように、私の主な問題はSQLではなく、設定を解析する...ありがとう。 –

関連する問題