2017-09-15 104 views
0

我有一個段落,我想通過從單詞中分離標點符號來標記它,並打印結果。有一些特殊情況(縮寫,如美國&,如彼得的撇號,以及十進制數字)應附加在信件上,不要將它們分開。正則表達式模式的縮寫和標點符號

我運行下面的代碼:

import re 

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. 
Peter's house! 3,500 calorie rule, which equates a weight alteration 
of 2.2 lb" 

pattern = r"""(?:[A-Z]\.)+ |\d+(?:\.\d+)?%?|\w/.+$\s-|\w+(?:[-']\w+)*| 
(?:[+/\[email protected]&*]|/.$/)""" 

print (re.findall(pattern, text)) 

輸出:

['My', 'weight', 'is', 'about', '68', 'kg', '+', '/', '-', '10', 
'grams', 'I', 'live', 'in', 'U.S.A. ', 'at', 'Mr', "Peter's", 'house', 
'3', '500', 'calorie', 'rule', 'which', 'equates', 'a', 'weight', 
'alteration', 'of', '2.2', 'lb' 
] 

有一些錯誤與此代碼,我真的很需要幫助解決這些問題:

  1. 它刪除所有的標點符號!我想保留它們,但是與單詞分離。

  2. 該模式忽略數字包含(,)並將其刪除。我已將\d+(?:\,\d+)?%?添加到該模式,但無法正常工作。

  3. 模式也忽略了一些縮寫,如Mr.

您的幫助將是非常讚賞!

+0

我不認爲這是完全可能的。正則表達式應該如何知道「美國」的最後一點?是否結束句子? – Emaro

回答

1

我會建議你避免試圖用正則表達式來做這件事,並使用一個專爲工作而設計的工具。下面應處理U.S.A.Peter's

from nltk.tokenize import WhitespaceTokenizer, word_tokenize 

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. Peter's house! 3,500 calorie rule, which equates a weight alteration of 2.2 lb" 

print WhitespaceTokenizer().tokenize(text) 
print word_tokenize(text) 

這會給你以下可能性:

['My', 'weight', 'is', 'about', '68', 'kg,', '+/-', '10', 'grams!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', "Peter's", 'house!', '3,500', 'calorie', 'rule,', 'which', 'equates', 'a', 'weight', 'alteration', 'of', '2.2', 'lb'] 
['My', 'weight', 'is', 'about', '68', 'kg', ',', '+/-', '10', 'grams', '!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', 'Peter', "'s", 'house', '!', '3,500', 'calorie', 'rule', ',', 'which', 'equates', 'a', 'weight', 'alteration', 'of', '2.2', 'lb'] 
+0

好吧,我會確定使用這個工具,但輸出中有錯誤。 「克!」中的標點符號和'房子!'應該從這個詞溢出。所以,正確的輸出應該是'克','!','房子','!'在這種情況下,我可以使用這個代碼的正則表達式嗎? –

+0

您也可以調查'word_tokenize()'作爲替代。我已經更新了腳本。 –

+0

感謝您的更新。第二個輸出中的問題是,名字彼得的撇號是分開的,它不應該。'Peter',''s「 –

0

如果你不打算用完全成熟的自然語言處理工具的工作,我建議你使用一個更簡單的模式並計劃一些post解析清理。試圖解決模式匹配中的一切都很棘手,並且可能會隨着新語法元素的引入而繼續失敗。這就是說,這裏有一個簡單的模式方法,我相信處理了大部分,有關你的例外:

import re 

text = "My weight is about 68 kg, +/- 10 grams! I live in U.S.A. at Mr. Peter's house! 3,500 calorie rule, which equates a weight alteration of 2.2 lb" 

pattern = r"(\s+|(?:[A-Z']\.?)+)" 

tokens = [token for token in re.split(pattern, text, flags=re.I) if token and not token.isspace()] 

print(tokens) 

輸出

['My', 'weight', 'is', 'about', '68', 'kg', ',', '+/-', '10', 'grams', 
'!', 'I', 'live', 'in', 'U.S.A.', 'at', 'Mr.', "Peter's", 'house', '!', 
'3,500', 'calorie', 'rule', ',', 'which', 'equates', 'a', 'weight', 
'alteration', 'of', '2.2', 'lb'] 

不是re.findall(),我使用re.split()與模式保持隔離令牌在字符串中(即我們分開單詞)。隨着新的例外情況出現,評估是否值得使模式複雜化,或者是否可以在解析前或解析後處理它們。

+0

非常感謝你的代碼。它工作正常,因爲我想要的輸出。我想知道如果我想使用nltk.tokenize。我應該使用正則表達式嗎?或代碼將更簡單 –

+0

我用你的模式nltk&python 3 regexp_tokenize(text,pattern =(「\ s + |(?:[A-Z'] \。?)+」)),但它顯示了我此:[ 'M', '', '', '', '', '', '', '', '', '', 'I', ' ' '', '', 'USA', '', '', 'M', '', 'P', 「'」, '', ' ' '', '', '', '', '', '', '', '', '', '「] –

+0

@BeautifulMind,正如我所提到的我的解釋是,我的模式是爲're.split()'設計的,它應用了與其他正則表達式不同的模式,接下來是理解去除空字符串和空白。 'regexp_tokenize()'函數以不同的方式應用模式,[在regexp_tokenize()源文件頂部的代碼註釋中總結了這些模式。](http://www.nltk.org/_modules/nltk/tokenize/ regexp.html) – cdlane