2012-03-12 7 views
4

私はまだカバーする方法がわからない特別な使用例があります。私はfield_name/field_lengthに基づいて文字列を解剖したい。そのために私は次のような正規表現を定義します:名前付きグループと代入を使用してPython正規表現で文字列を解読する

'(?P<%s>.{%d})' % (field_name, field_length) 

これをすべてのフィールドについて繰り返します。

私はまた、各フィールドの右にあるスペースを削除する正規表現を持っている:

self.re_remove_spaces = re.compile(' *$') 

私はこのような各フィールドを取得することができますこの方法:

def dissect(self, str): 
    data = { } 
    m = self.compiled.search(str) 
    for field_name in self.fields: 
     value = m.group_name(field_name) 
     value = re.sub(self.re_remove_spaces, '', value) 
     data[field_name] = value 
    return data 

私は、この処理を実行する必要があります何百万という文字列なので、効率的でなければなりません。

compiled.searchの代わりにcompiled.subを使用して、解剖+空間の除去を1回のステップで実行することをお勧めしますが、これを行う方法はわかりません。

具体的には、私の質問は:

どのように私はPythonの正規表現で指定されたグループと組み合わせ正規表現置換を行うのですか?

+0

''(?​​<%s>。%d)'%...'は ''(?​​ .12)''のようになりますが、有効なPython正規表現ではありません。 – interjay

+0

申し訳ありません、修正:Pと{}が見つかりませんでした。私はまだこれをテストしているので、より多くのバグが存在する可能性があります。 – dangonfast

答えて

4

私は例えば、それは、各フィールドがテーブルのように、文字列で隣同士に座って取る:

name  description  license 
python language   opensource 
windows operating system proprietry 

したがって、各フィールドの長さを事前に知っていると仮定すれば、正規表現をまったく使用することなく、もっと簡単に行うことができます。

>>> self.dissect('python language   opensource') 
{'lang': 'python', 'license': 'opensource', 'desc': 'language'} 

が、これはあなたががやるしようとしているものです:fields = [('lang', 9), ('desc', 19), ('license', 12)]場合、その後

def dissect(text): 
    data = {} 
    for name, length in fields: 
     data[name] = text[:length].rstrip() 
     text = text[length:] 
    return data 

(それが組み込みstrタイプと衝突するのでところで、strは、変数のための良い名前ではありませんか)?

+0

はい、これはまさに私が試みていることです。実際には、最初の実装は文字列スライスを使用して行われました。どういうわけか、私は、正規表現がこのシナリオでよりうまく実行されることを確信し、実装を名前付きグループと正規表現に変更しました。私のプロセス機能は現在数時間稼働しており、実際にスライスが速いという気持ちがあることを伝えています。おそらく私はそれを元に戻すか、両方の実装でパフォーマンステストを行うようにしています。 – dangonfast

+0

スライスが大幅に高速になっていることがわかりますが、そのスライスが長時間実行されていれば、それをプロファイルしてボトルネックがどこにあるのか、それをさらにスピードアップする方法を確認する必要があります。 – aquavitae

+0

処理するレコードがたくさんあるので、時間がかかります。 – dangonfast

0

subを使用すると、あなたが直接必要な部分にマッチすることができます。

あなたが好きなものを使用することができます

(?P<name>.{0,N}(?<!)) 

しかし、試合は正確N長くする必要があれば、あなたは同じように、先読みを使用することができます。これは使用してより良い実行している場合

(?=(?P<name>.{0,N}(?<!))).{N} 

追加のトリムは疑わしい。あなたはそれを試して私たちに知らせることができます。

これらの式は、一致するものがスペースのみで、文字がスペースでもある場合は機能しません。あなたが動作するようにそのケースが必要な場合は、グループの最後に|を追加することができます。

(?P<name>.{0,N}(?<!)|) 
+0

はい、フィールドはすべてスペースにすることができ、先頭フィールドにはスペースを使用することもできます。フィールドは正確な長さです。 – dangonfast

+0

@gonvaledの場合、最後の候補を含む2番目の式を使用できます。 '(?=(?P 。{0、N}(?<!)|))。{N}' – Qtax

+0

入力を変更できません。データ。 '|'を追加することはできません。 – dangonfast

関連する問題