2

Psycopg2 から返されたネストされた配列の解析に問題があります。私が取り組んでいるDBは、ネストされた配列を値として持つことができるレコードを返します。Psycopg は、そのような値の外側の配列のみを解析します。

私の最初のアプローチはコンマで文字列を分割することでしたが、結果内の文字列にもコンマが含まれていることがあり、アプローチ全体が使用できなくなるという問題に遭遇しました。次の試みは、正規表現を使用して文字列内の「コンポーネント」を見つけることでしたが、数字を検出できないことに気付きました (数字は文字列内でも発生する可能性があるため)。

現在、これは私のコードです:

import re
text = '{2f5e5fef-1e8c-43a2-9a11-3a39b2cbb45e,"Marc, Dirk en Koen",398547,85.5,-9.2, 62fe6393-00f7-418d-b0b3-7116f6d5cf10}'
r = re.compile('\".*?\"|[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}|^\d*[0-9](|.\d*[0-9]|,\d*[0-9])?$')
result = r.search(text)
if result:
    result = result.groups()

この結果は次のようになります。

['2f5e5fef-1e8c-43a2-9a11-3a39b2cbb45e', 'Marc, Dirk en Koen', 398547, 85.5, -9.2, '62fe6393-00f7-418d-b0b3-7116f6d5cf10']

この機能を汎用にしたいので、引数の順序について確信が持てません。サポートされている型が文字列、uuid、(符号付き) 整数、(符号付き) 10 進数であることだけは知っています。

間違ったアプローチを使用していますか? または、誰かが私を正しい方向に向けることができますか?

前もって感謝します!

4

5 に答える 5

3

Python のネイティブ ライブラリはうまく機能するはずです。もう試しましたか?

http://docs.python.org/library/csv.html

于 2011-02-14T16:22:07.393 に答える
0

あなたのサンプルから、それは私には何かのように見え^{(?:(?:([^},"']+|"[^"]+"|'[^']+')(?:,|}))+(?<=})|})$ます。「{foo、bar} baz}」が許可されるため、これは完全ではありませんが、問題があれば修正できます。

于 2011-02-14T16:18:08.870 に答える
0

アサーションを行うことができれば、正しい軌道に乗ることができます。

この問題は広範すぎて、単一の正規表現で解決できません。グローバルマッチで同時に検証と解析を試みています。ただし、意図した結果には、一致後にサブ処理が必要です。そのため、より単純なグローバル パーサーを記述してから、検証と修正のために結果を繰り返し処理することをお勧めします (そうです、例では修正が規定されています)。

2 つの主な解析正規表現は次のとおりです。

  1. 区切り引用符も削除し、$2 のみにデータが含まれています。while ループで使用し、グローバル コンテキストを使用します。
    /(?!}$)(?:^{?|,)\s*("|)(.*?)\1\s*(?=,|}$)/

  2. 私の好みは、引用符を削除せず、$1 のみをキャプチャし、配列または while ループ、グローバル コンテキストでキャプチャするために使用できます
    /(?!}$)(?:^{?|,)\s*(".*?"|.*?)\s*(?=,|}$)/

これは文書化された正規表現を使用した (Perl での) 後処理の例です: (編集: 付加末尾を修正 , )

use strict; use warnings;

my $str = '{2f5e5fef-1e8c-43a2-9a11-3a39b2cbb45e,"Marc, Dirk en Koen",398547,85.5,-9.2, 62fe6393-00f7-418d-b0b3-7116f6d5cf10}';

my $rx = qr/ (?!}$) (?:^{?|,) \s* ( ".*?" | .*?) \s* (?=,|}$) /x;

my $rxExpanded = qr/
         (?!}$)           # ASSERT ahead:  NOT a } plus end
         (?:^{?|,)        # Boundry: Start of string plus { OR comma
         \s*              # 0 or more whitespace
         ( ".*?" | .*?)   # Capture "Quoted" or non quoted data
         \s*              # 0 or more whitespace
         (?=,|}$)         # Boundry ASSERT ahead:  Comma OR } plus end
  /x;

my ($newstring, $sucess) = ('[', 0);

for my $field ($str =~ /$rx/g)
{
   my $tmp = $field;
   $sucess = 1;

   if (  $tmp =~ s/^"|"$//g || $tmp =~ /(?:[a-f0-9]+-){3,}/ ) {
      $tmp = "'$tmp'";
   }
   $newstring .= "$tmp,";
}
if ( $sucess ) {
    $newstring =~ s/,$//;
    $newstring .= ']';
    print $newstring,"\n";
}
else {
    print "Invalid string!\n";
}

出力:
['2f5e5fef-1e8c-43a2-9a11-3a39b2cbb45e','Marc, Dirk en Koen',398547,85.5,-9.2,'6 2fe6393-00f7-418d-b0b3-7116f6d5cf10']

于 2011-02-14T18:52:00.403 に答える
0

CSV アプローチが最も簡単に実装できるように思われました。

def parsePsycopgSQLArray(input):
    import csv
    import cStringIO

    input = input.strip("{")
    input = input.strip("}")

    buffer = cStringIO.StringIO(input)
    reader = csv.reader(buffer, delimiter=',', quotechar='"')   

    return reader.next() #There can only be one row 

if __name__ == "__main__":
    text = '{2f5e5fef-1e8c-43a2-9a11-3a39b2cbb45e,"Marc, Dirk en Koen",398547,85.5,-9.2, 62fe6393-00f7-418d-b0b3-7116f6d5cf10}' 
    result = parsePsycopgSQLArray(text)
    print result

回答ありがとうございます。とても役に立ちました。

于 2011-02-15T09:16:23.900 に答える