2015-09-04 45 views
0

我是比較新的正則表達式(總是與它掙扎出於某種原因)...Python的正則表達式來分析財務數據

我有文字是這樣的形式:

David Meredith, Financial Director sold post-exercise 15,000 shares in the company on YYYY-mm-dd at a price of 1044.00p. The Director now holds 6,290 shares representing 0.01% of the... 

Mark Brookes, Non Executive Director bought 811 shares in the company on YYYY-mm-dd at a price of 76.75p. The Director now holds 189,952 shares representing 0.38% of the shares in... 

Albert Ellis, CEO bought 262 shares in the company on YYYY-mm-dd at a price of 52.00p. The Director now holds 465,085 shares. NOTE: Purchased through Co's SIP Story provided by... 

解析文本揭示了以下結構:開頭的句子

  1. 兩個或更多的話,第一個逗號之前,是參與交易的人的名字
  2. 之前的一個或多個單詞('sold'|''買入'|'已行使'|'已售出post exercise')是該人的頭銜
  3. 存在以下任何一種情況:('sold'|'buy' |'已行使'|'賣出後行使')標題之後,標識交易類型
  4. 交易類型後面的第一個數字字符串('sold'|'買過'|'已行使'|'售出後行使')表示交易規模
  5. '價格'在數字字符串前面,該數字字符串指定交易被觸發的價格。

我的問題是:

如何使用這方面的知識(和正則表達式),編寫分析類似的文本返回感興趣的變量的函數(上市1 - 5以上)?

爲我想寫功能..

def grok_directors_dealings_text(text_input): 
    name, title, transaction_type, lot_size, price = (None, None, None, None, None) 
    .... 
    name = ... 
    title = ... 
    transaction_type = ... 
    lot_size = ... 
    price = ... 

    pass 

我將如何使用正則表達式來實現的函數返回感興趣的變量符合我有結構化文本傳遞時的僞代碼以上確定?

[編輯]

出於某種原因,我似乎與正則表達式鬥爭了一段時間,如果我從這裏開始,因此正確答案的學習,它會更好,如果關於爲什麼神奇表達(對不起,regexpr)實際上起作用的解釋。

我想真正瞭解這種東西,而不是複製粘貼的表情......

回答

2

您可以使用下面的正則表達式:

(.*?),\s(.*)\s(sold(?: post-exercise)?|bought|exercised)\s*([\d,]*).*price of\s*(\d*.\d+?p) 

DEMO

Python:

import re 

financialData = """ 
David Meredith, Financial Director sold post-exercise 15,000 shares in the company on YYYY-mm-dd at a price of 1044.00p. The Director now holds 6,290 shares representing 0.01% of the... 

Mark Brookes, Non Executive Director bought 811 shares in the company on YYYY-mm-dd at a price of 76.75p. The Director now holds 189,952 shares representing 0.38% of the shares in... 

Albert Ellis, CEO bought 262 shares in the company on YYYY-mm-dd at a price of 52.00p. The Director now holds 465,085 shares. NOTE: Purchased through Co's SIP Story provided by... 
""" 

print(re.findall('(.*?),\s(.*)\s(sold(?: post-exercise)?|bought|exercised)\s*([\d,]*).*price of\s*(\d*.\d+?p)',financialData)) 

輸出:

[('David Meredith', 'Financial Director', 'sold post-exercise', '15,000', '1044.00p'), ('Mark Brookes', 'Non Executive Director', 'bought', '811', '76.75p'), ('Albert Ellis', 'CEO', 'bought', '262', '52.00p')] 

編輯1

要了解如何以及他們的意思,按照DEMO鏈接,在右上角,你可以找到一個塊解釋什麼是每字符意思如下:

enter image description here

另外Debuggex可以幫助您通過顯示哪些組匹配哪些字符來模擬字符串!

這裏是爲您的特定情況下,debuggex演示:

(.*?),\s(.*)\s(sold(?: post-exercise)?|bought|exercised)\s*([\d,]*).*price of\s*(\d*.\d+?p) 

Regular expression visualization

Debuggex Demo

+1

我敬畏正則表達式的力量 - 但請你解釋它是如何正確匹配的?我不能在我對文本結構的描述和你創建的表達之間進行映射 - 你能否將它分解成一個凡人? –

+0

@HomunculusReticulli,很難在單個答案中解釋有關正則表達式的所有內容,如果您想快速分析正則表達式,希望您發現它們有幫助,如果您想挖掘更多內容,請嘗試閱讀'掌握正則表達式'傑弗裏弗裏德爾' –

0

這是一個會做

(.*?),(.*?)(sold post-exercise|sold|bought|exercised).*?([\d|,]+).*?price of ([\d|\.]+) 

的正則表達式,你使用這樣

import re 
def get_data(line): 
    pattern = r"(.*?),(.*?)(sold post-exercise|sold|bought|exercised).*?([\d|,]+).*?price of ([\d|\.]+)" 
    m = re.match(pattern, line) 
    return m.groups() 

第一行這將返回

('David Meredith','財務總監」,‘賣運動後’,'15,000' ,‘1044.00’) 編輯: 加解釋

這個表達式的工作原理如下 的第一個字符(*),平均 - 以字符串直到下一個?匹配(女巫是,)

。意味着每一個字符

的*意味着它可以多次(多個字符,而不是僅僅1)

?意味着它將使用第一個','和另一個(如果有很多',')

之後有這個再次(。*?) 再次採取字符,直到接下來的事情,以配合(用的是恆定的話)之後

有(出售後鍛鍊|賣|買|行使)巫指 - 找到一家之言(由sperated |)

後有一個。*?女巫再次意味着採取所有文字,直到下一場比賽(這一次它沒有被()所包圍,所以它不會被選爲一個組,並且不會成爲輸出的一部分)

([\ d |,] +)一個數字(\ d)或一個逗號。 +代表一次或多次

再次。*?像以前一樣

「的價格」查找

和最後的實際字符串「的價格」([\ d |。] +)指再取一個數字或一個點(轉義,因爲該字符被用於通過。的正則表達式「任何字符」)一次或多次

0

您可以使用下面的正則表達式,只是查找周邊的分隔符字符:

(.*?), (.*?) (sold post-exercise|bought|exercised|sold) (.*?) shares .*? price of (.*?)p 

括號中的部分將被捕捉爲組。

>>> import re 
>>> l = ['''David Meredith, Financial Director sold post-exercise 15,000 shares in the company on YYYY-mm-dd at a price of 1044.00p. The Director now holds 6,290 shares representing 0.01% of the...''', '''Mark Brookes, Non Executive Director bought 811 shares in the company on YYYY-mm-dd at a price of 76.75p. The Director now holds 189,952 shares representing 0.38% of the shares in...''', '''Albert Ellis, CEO bought 262 shares in the company on YYYY-mm-dd at a price of 52.00p. The Director now holds 465,085 shares. NOTE: Purchased through Co's SIP Story provided by...'''] 
>>> for s in l: 
...  print(re.findall(r'(.*?), (.*?) (sold post-exercise|bought|exercised|sold) (.*?) shares .*? price of (.*?)p', s)) 
... 
[('David Meredith', 'Financial Director', 'sold post-exercise', '15,000', '1044.00')] 
[('Mark Brookes', 'Non Executive Director', 'bought', '811', '76.75')] 
[('Albert Ellis', 'CEO', 'bought', '262', '52.00')] 
1

我想出了這個正則表達式:

([\w ]+), ([\w ]+) (sold post-exercise|sold|bought|exercised) ([\d,\.]+).*price of ([\d\.,]+)p 

Regular expression visualization

Debuggex Demo

基本上,我們使用括號來捕捉你想要這樣的重要信息,讓我們看看每一個:

  • ([\w ]+)\w一次或多次匹配任何單詞字符[a-zA-Z0-9_],這會給我們一個人的名字;
  • ([\w ]+)其中一個用空格和逗號取得標題;
  • (sold post-exercise|sold|bought|exercised)然後我們搜索我們的交易類型。注意我把post-exercise放在post之前,這樣它就會首先匹配較大的單詞;
  • ([\d,\.]+)然後我們試着找出由數字組成的數字(\d),逗號和可能出現的點也可能出現;
  • ([\d\.,]+)然後我們需要得到與交易規模基本相同的價格。

連接每個組的正則表達式也非常基本。

如果你嘗試在regex101它提供了有關正則表達式的一些解釋和Python的生成此代碼使用方法:

import re 
p = re.compile(ur'([\w ]+), ([\w ]+) (sold post-exercise|sold|bought|exercised) ([\d,\.]+).*price of ([\d\.,]+)p') 

test_str = u"David Meredith, Financial Director sold post-exercise 15,000 shares in the company on YYYY-mm-dd at a price of 1044.00p. The Director now holds 6,290 shares representing 0.01% of the...\n\nMark Brookes, Non Executive Director bought 811 shares in the company on YYYY-mm-dd at a price of 76.75p. The Director now holds 189,952 shares representing 0.38% of the shares in...\n\nAlbert Ellis, CEO bought 262 shares in the company on YYYY-mm-dd at a price of 52.00p. The Director now holds 465,085 shares. NOTE: Purchased through Co's SIP Story provided by..." 

re.findall(p, test_str) 
+0

好吧,這是我可以種遵循怎麼回事的邏輯的第一個答案。順便說一句,我稍微修改了我的問題(請再看一下)。我忘記了提取價格。 –

+0

@HomunculusReticulli - 請注意,它被認爲是可憐的形式,以一種使現有答案無效的方式實質性地改變問題。儘量避免在將來這樣做。 – TigerhawkT3

+0

@Homunculus Reticulli,我更新了答案。 –