2016-07-06 57 views
2

我有一個這樣的字符串:的Python:替換字符串中的「啞引號」與「花一」

「可是那位先生,」望着達西,「似乎認爲這個國家是什麼都沒有「。

我想這樣的輸出:

「可是那位先生,」望着達西,「似乎認爲這個國家是什麼都沒有」

同樣,啞單引號應該轉換自己的捲曲等價物。 Read about the typographic rules here if you are interested.

我的猜測是,這已經解決了,但我找不到一個庫或腳本來做到這一點。 SmartyPants(Perl)是做這個的所有庫的母親,並且有一個python port。但它的輸出是HTML實體:“But that gentleman,”我只想要一個帶有引號的簡單字符串。有任何想法嗎?

更新:

我解決了它的建議通過哈靈頓坎寧安:

  1. 使用聰明的傢伙,使印刷更正
  2. 使用HTMLParser().unescape到HTML實體轉換回爲Unicode

如果您的輸入文本包含HTML e,則此方法可能存在問題你不希望轉換的實體,但在我的情況下是可以的。更新

到底能輸入被信任?

輸入目前只能被信任。該字符串可能包含一個非關閉的雙引號:"But be that gentleman, looking at Dary。它也可能包含一個非封閉的單引號:'But be that gentleman, looking at Dary。最後,它可能包含一個意思是撇號的單引號:Don't go there.

我已經實現了一個試圖正確關閉這些丟失的引號的算法,所以這不是問題的一部分。爲了完整起見,這裏是關閉失去報價代碼:

quotationMarkDictionary = [{ 
    'start': '"', 
    'end': '"', 
    },{ 
    'start': '「', 
    'end': '」', 
    },{ 
    'start': '\'', 
    'end': '\'', 
    },{ 
    'start': '‘', 
    'end': '’' 
    },{ 
    'start': '(', 
    'end': ')' 
    },{ 
    'start': '{', 
    'end': '}' 
    },{ 
    'start': '[', 
    'end': ']' 
    }] 

'''If assumedSentence has quotation marks (single, double, …) and the 
number of opening quotation marks is larger than the number of closing  
quotation marks, append a closing quotation mark at the end of the 
sentence. Likewise, add opening quotation marks to the beginning of the 
sentence if there are more closing marks than opening marks.''' 
for quotationMark in quotationMarkDictionary: 
    numberOpenings = assumedSentence['sentence'].count(quotationMark['start']) 
    numberClosings = assumedSentence['sentence'].count(quotationMark['end']) 
    # Are the opening and closing marks the same? ('Wrong' marks.) Then just make sure there is an even number of them 
    if quotationMark['start'] is quotationMark['end'] and numberOpenings % 2 is not 0: 
    # If sentence starts with this quotation mark, put the new one at the end 
    if assumedSentence['sentence'].startswith(quotationMark['start']): 
     assumedSentence['sentence'] += quotationMark['end'] 
    else: 
     assumedSentence['sentence'] = quotationMark['end'] + assumedSentence['sentence'] 
    elif numberOpenings > numberClosings: 
    assumedSentence['sentence'] += quotationMark['end'] 
    elif numberOpenings < numberClosings: 
    assumedSentence['sentence'] = quotationMark['start'] + assumedSentence['sentence'] 
+0

你到目前爲止試過了什麼?你相信你的投入多少?報價是否總是正確配對? – user1582024

+0

這裏你去 - https://gist.github.com/davidtheclark/5521432 – hashcode55

+0

@ hashcode55這產生HTML實體,而不是純文本。 – bootsmaat

回答

1

可以使用HTMLParser反轉義的HTML實體從聰明的傢伙回來:

In [32]: from HTMLParser import HTMLParser 

In [33]: s = "&#x201C;But that gentleman,&#x201D;" 

In [34]: print HTMLParser().unescape(s) 
「But that gentleman,」 
In [35]: HTMLParser().unescape(s) 
Out[35]: u'\u201cBut that gentleman,\u201d' 

要avoin編碼錯誤,您應該在打開文件時使用io.open並指定encoding="the_encoding"或解碼字符串轉換爲Unicode:

In [11]: s 
Out[11]: '&#x201C;But that gentleman,&#x201D;\xe2' 

In [12]: print HTMLParser().unescape(s.decode("latin-1")) 
「But that gentleman,」â 
+0

好主意,但我得到一個錯誤。該字符串之前已經從.txt文件中讀取。 回溯(最近通話最後一個): 文件 「/Users/bildlich/Development/textfiles-to-mongodb/textfiles-to-mongodb.py」,線路173,在 assumedSentences.extend(fileToSentenceList(textFilesDirectory +文件名) ) 文件「/Users/bildlich/Development/textfiles-to-mongodb/textfiles-to-mongodb.py」,第147行,在fileToSentenceList中 numberOpenings = assumeSentence ['sentence']。count(quotationMark ['start']) UnicodeDecodeError:'ascii'編解碼器無法解碼位置0中的字節0xe2:序號不在範圍內(128) – bootsmaat

+1

確定,因此它是拉丁編碼的數據?基本上你試圖將一個ascii字符串連接到一個latin-1編碼字符串,你可以在任何地方使用unicode,並在需要時編碼爲str。 –

+0

感謝您的提示。我通過A)解決了這個問題,確保輸入的文本使用io.open編碼爲UTF-8,B)編碼UTF-8中的quotationMark ['start']。 – bootsmaat

0

通過文檔掃視了一眼,它看起來你堅持.replace在聰明的傢伙的頂部:

smartypants(r'"smarty" \"pants\"').replace('&#x201C;', '「').replace('&#x201D;', '」') 

可能會讀更好的是,如果你別名的魔術弦,但:

html_open_quote = '&#x201C;' 
html_close_quote = '&#x201D;' 
smart_open_quote = '「' 
smart_close_quote = '」' 
smartypants(r'"smarty" \"pants\"') \ 
    .replace(html_open_quote, smart_open_quote) \ 
    .replace(html_close_quote, smart_close_quote) 
+0

我不確定我是否理解。你是否建議使用smartypants來獲取HTML實體,然後將這些實體解碼爲純文本? – bootsmaat

0

假設輸入良好,這可以使用正則表達式附件:

# coding=utf8 
import re 
sample = '\'Sample Text\' - "But that gentleman," looking at Darcy, "seemed to think the \'country\' was nothing at all." \'Don\'t convert here.\'' 
print re.sub(r"(\s|^)\'(.*?)\'(\s|$)", r"\1‘\2’\3", re.sub(r"\"(.*?)\"", r"「\1」", sample)) 

輸出:

‘Sample Text’ - 「But that gentleman,」 looking at Darcy, 「seemed to think the ‘country’ was nothing at all.」 ‘Don't convert here.’ 

我假設這裏分離出單引號,他們要麼是在一行的開始/結束或有他們周圍的空白。