12

(ドイツの) 銀行からのトランザクション レターを解析しようとしています。次の文字列からすべての数字を抽出したいのですが、思ったより難しいことがわかりました。オプション2は、私が望むほとんどのことを行います。私は今、例えば80もキャプチャするように変更したいと考えています。

私の最初の試みは、ガベージのみを返すオプション 1 です。多くの空の文字列が返されるのはなぜですか? 少なくとも最初の \d+ からの数字が必ずあるはずですよね?

オプション 3 が機能する (または少なくとも期待どおりに機能する) ので、どういうわけか私は自分の質問に答えています。オプション2が機能しない理由について、私は主に頭を悩ませていると思います。

# -*- coding: utf-8 -*-
import re


my_str = """
Dividendengutschrift für inländische Wertpapiere

Depotinhaber    : ME

Extag           :  18.04.2013          Bruttodividende
Zahlungstag     :  18.04.2013          pro Stück       :       0,9800 EUR
Valuta          :  18.04.2013

                                       Bruttodividende :        78,40 EUR
                                      *Einbeh. Steuer  :        20,67 EUR
                                       Nettodividende  :        78,40 EUR

                                       Endbetrag       :        57,73 EUR
"""

print re.findall(r'\d+(,\d+)?', my_str)
print re.findall(r'\d+,\d+', my_str)
print re.findall(r'[-+]?\d*,\d+|\d+', my_str)

出力は

['', '', '', '', '', '', ',98', '', '', '', '', ',40', ',67', ',40', ',73']
['0,9800', '78,40', '20,67', '78,40', '57,73']
['18', '04', '2013', '18', '04', '2013', '0,9800', '18', '04', '2013', '78,40', '20,67', '78,40', '57,73']
4

7 に答える 7

12

オプション 1 は正規表現の中で最も適していますが、完全な一致ではなく、findallキャプチャ グループによって一致したものが返されるため、正しく機能していません。()

たとえば、この例の最初の 3 つの一致は1804および2013であり、それぞれの場合でキャプチャ グループが一致しないため、空の文字列が結果リストに追加されます。

解決策は、グループを非キャプチャにすることです

r'\d+(?:,\d+)?'

オプション 2 は、コンマを含まないシーケンスと一致しない限り機能しません。

オプション 3 は、たとえば+,1.

于 2013-05-01T15:33:25.813 に答える
9

次の文字列からすべての数字を抽出したいのですが...

「数字」とは、通貨量と日付の両方を意味する場合、これで目的が達成されると思います。

print re.findall(r'[0-9][0-9,.]+', my_str)

出力:

['18.04.2013', '18.04.2013', '0,9800', '18.04.2013', '78,40', '20,67', '78,40', '57,73']

「数字」が通貨金額のみを意味する場合は、次を使用します

print re.findall(r'[0-9]+,[0-9]+', my_str)

または、さらに良いかもしれませんが、

print re.findall(r'[0-9]+,[0-9]+ EUR', my_str)
于 2013-05-01T15:35:56.273 に答える
2

これは、ステートメントを解析し、結果を という辞書に入れるソリューションですbank_statement

# -*- coding: utf-8 -*-
import itertools

my_str = """
Dividendengutschrift für inländische Wertpapiere

Depotinhaber    : ME

Extag           :  18.04.2013          Bruttodividende
Zahlungstag     :  18.04.2013          pro Stück       :       0,9800 EUR
Valuta          :  18.04.2013

                                       Bruttodividende :        78,40 EUR
                                      *Einbeh. Steuer  :        20,67 EUR
                                       Nettodividende  :        78,40 EUR

                                       Endbetrag       :        57,73 EUR
"""

bank_statement = {}

for line in my_str.split('\n'):
    tokens = line.split()
    #print tokens


    it = iter(tokens)
    category = ''
    for token in it:
        if token == ':':
            category = category.strip(' *')
            bank_statement[category] = next(it)
            category = ''
        else:
            category += ' ' + token

# bank_statement now has all the values
print '\n'.join('{0:.<18} {1}'.format(k, v) \
                for k, v in sorted(bank_statement.items()))

このコードの出力:

Bruttodividende... 78,40  
Depotinhaber...... ME  
Einbeh. Steuer.... 20,67  
Endbetrag......... 57,73  
Extag............. 18.04.2013  
Nettodividende.... 78,40  
Valuta............ 18.04.2013  
Zahlungstag....... 18.04.2013  
pro Stück........ 0,9800  

討論

  • コードは、ステートメント文字列を 1 行ずつスキャンします。
  • 次に、各行をトークンに分割します
  • トークンをスキャンしてコロンを探します。見つかった場合は、コロンの前の部分をカテゴリとして使用し、その後の部分を値として使用します。bank_statement['Extag']たとえば、値は「18.04.2013」です
  • すべての値は数値ではなく文字列であることに注意してください。ただし、それらを変換するのはトリビアです。
于 2013-05-01T16:07:03.360 に答える
1

この質問は関連しています。以下

print re.findall(r'\d+(?:,\d+)?', my_str)
                       ^^     

出力

['18', '04', '2013', '18', '04', '2013', '0,9800', '18', '04', '2013', '78,40', '20,67', '78,40', '57,73']

「ドット付き」の数字を除外するのはもう少し複雑です:

print re.findall(r'(?<!\d\.)\b\d+(?:,\d+)?\b(?!\.\d)', my_str)
                   ^^^^^^^^^^^            ^^^^^^^^^^

これは出力します

['0,9800', '78,40', '20,67', '78,40', '57,73']
于 2013-05-01T15:29:37.907 に答える