[英]Removing symbols from a large unicode text file
我有一個文本文件,其中包含大約2GB
大小的Unicode文本。 我嘗試使用以下代碼刪除所有符號
import re
symbols = re.compile(r'[{} &+( )" =!.?.:.. / | » © : >< # « ,] 1 2 3 4 5 6 7 8 9 _ - + ; [ ] %',flags=re.UNICODE)
with open('/home/corpus/All12.txt','a') as t:
with open('/home/corpus/All11.txt', 'r') as n:
data = n.readline()
data = symbols.sub(" ", data)
t.write(data)
用於測試代碼的小文件:
:621
"
:621 "
:621 :1 ;"
_ " :594 :25 4 8 0 :23 "സര്ക്കാര്ജീവനക്കാരുടെ ശമ്പളം അറിയാന് ഭാര്യമാര്ക്ക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്
:621 :4 0 3 0 ;"
_ " :551 :16 :3 "
:12 :70 ;" " " ="" " " ="" " " ="" +
_ " :541 :26 :30 45 5 35 "
=' 'ന്യൂഡല്ഹി: സര്ക്കാര്ജീവനക്കാരായ ഭര്ത്താക്കന്മാരുടെ ശമ്പളം
欲望的輸出是ന്യൂഡല്ഹി സര്ക്കാര്ജീവനക്കാരായ ഭര്ത്താക്കന്മാരുടെ ശമ്പളം
。 代碼無法正常運行。 它會停止我的電腦。
我可以用正則表達式來解決這個問題嗎?
您需要在方括號[]
插入要替換的每個符號,轉義一些特殊符號,如[]
本身,單引號'
和\\
。 正則表達式是r'[-0-9{}&+()"=!.?:/|»©><#«,_+;%\\[\\]@$*\\'\\\\^~\\n\\t]'
。
演示:
>>> st='1234567890-=[]\;,./\'!@#$%^&*()_+{}|":<>?//.,`~ajshgasd'
>>> print re.sub(r'[-0-9{}&+()"=!.?:/|»©><#«,_+;%\[\]@$*\'\\^`~\n\t]','',st)
ajshgasd
存檔:
>>> fp=open('file.txt','r')
>>> for line in fp:
... if line.strip() == '': continue # strip() removes leading and trailing spaces
... print re.sub(r'[-0-9{}&+()"=!.?:/|»©><#«,_+;%\[\]@$*\'\\^`~]','',line).strip(),
...
ന്യൂഡല്ഹി സര്ക്കാര്ജീവനക്കാരായ ഭര്ത്താക്കന്മാരുടെ ശമ്പളം
要將輸出寫入文件,請使用以下代碼:
of=open('outfile.txt','w')
fp=open('file.txt','r')
for line in fp:
if line.strip() == '': continue # strip() removes leading and trailing spaces
rline = re.sub(r'[-0-9{}&+()"=!.?:/|»©><#«,_+;%\[\]@$*\'\\^`~]','',line).strip()
if rline == '': continue # skip empty lines
of.write(rline+'\n')
of.close()
fp.close()
str.translate
可以用來代替re.sub
。 它將Unicode序數映射到替換對並返回已翻譯的字符串。 如果替換為None
則刪除字符。 str.maketrans
可用於生成映射。
在Python 3中,還要記住指定文件的編碼。 我使用UTF-8進行測試:
#!python3
#coding: utf8
symbols = ' {}&+()"=!.?.:../|»©:><#«,123456789_-+;[]%'
D = str.maketrans('','',symbols)
with open('All12.txt','a',encoding='utf8') as t, open('All11.txt','r',encoding='utf8') as n:
for line in n:
t.write(line.translate(D))
只需在symbols
列出要刪除的symbols
。
或者,您可以以字符塊的形式讀取文件,這比單獨讀取超過1000萬行更有效。 例如,在20+ 100MB塊中讀取文件。
#!python3
#coding: utf8
symbols = ' {}&+()"=!.?.:../|»©:><#«,123456789_-+;[]%'
D = str.maketrans('','',symbols)
with open('All12.txt','a',encoding='utf8') as t, open('All11.txt','r',encoding='utf8') as n:
while True:
block = n.read(100*1024*1024)
if not block:
break
t.write(block.translate(D))
參考: str.translate , str.maketrans
第一個[和]之間的符號列表之后的重新對我沒有意義。 它不會剝離符號,但只會刪除一個符號后跟'1 2 3 4 5 6 7 8 9 _ - +; []%'。 在其他工作中,re.sub將不會做任何事情。 但無論如何,你的代碼運行在3.4.2,Win7上。
import re
symbols = re.compile(r'[{} &+( )" =!.?.:.. / | » © : >< # « ,]'
'1 2 3 4 5 6 7 8 9 _ - + ; [ ] %',flags=re.UNICODE)
text = ('''" :621 " :621 :1 ;" _ " :594 :25 4 8 0 :23'''
'''"സര്ക്കാര്ജീവനക്കാരുടെ ശമ്പളം അറിയാന്'''
'''ഭാര്യമാര്ക്ക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്\n'''
''':621 :4 0 3 0 ;" _ " :551 :16 :3 " ''')
data = symbols.sub(" ", text)
print(data == text) # True
PS。 with
語句可以有多個子句(以保存縮進級別)。
with open('/home/corpus/All12.txt','a') as t,\
open('/home/corpus/All11.txt', 'r') as n:
[{} &+( )" =!.?.:.. / | » © : >< # « , 1 2 3 4 5 6 7 8 9 _ - + ; \[ \] %]
通過嘗試this.Replace empty string
。看到演示。
http://regex101.com/r/oE6jJ1/18
import re
p = re.compile(ur'[{} &+( )" =!.?.:.. / | » © : >< # « , 1 2 3 4 5 6 7 8 9 _ - + ; \[ \] %]', re.IGNORECASE | re.UNICODE)
test_str = u" :621 \" :621 :1 ;\" _ \" :594 :25 4 8 0 :23 \"സര്ക്കാര്ജീവനക്കാരുടെ ശമ്പളം അറിയാന് ഭാര്യമാര്ക്ക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്\n:621 :4 0 3 0 ;\" _ \" :551 :16 :3"
subst = u""
result = re.sub(p, subst, test_str)
解決方案沒有REGEX:
您可以使用map函數以及要刪除的一組符號來完成此操作。
def removeSymbols(text,symbols):
return "".join(map(lambda x: "" if x in symbols else x,text))
>>> string = '''" :621 \" :621 :1 ;\" _ \" :594 :25 4 8 0 :23 \"സര്ക്കാര്ജീവനക്കാരുടെ ശമ്പളം അറിയാന് ഭാര്യമാരക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്\n:621 :4 0 3 0 ;\" _ \" :551 :16 :3"'''
>>> symbols = set('[{} &+( )" =!.?.:.. / | » © : >< # « ,] 1 2 3 4 5 6 7 8 9 _ - + ; [ ] %')
>>> cleanString = removeSymbols(string,symbols)
>>> print(cleanString)
'" :621 " :621 :1 ;" _ " :594 :25 4 8 0 :23 "സര്\u200dക്കാര്\u200dജീവനക്കാരുടെ ശമ്പളം അറിയാന്\u200d ഭാര്യമാര്\u200dക്ക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്\u200d\n:621 :4 0 3 0 ;" _ " :551 :16 :3"'
我認為你的正則表達式不正確,因為你可以簡化它。 例如,子表達式[{} &+( )" =!.?.:.. / | » © : >< # « ,]
可以簡化為[ !"#&()+,./:<=>?{|}©«»]
:只保留每個角色一次。 這是因為[]
用於表示一組字符。 請查看Python文檔中的“正則表達式操作”一章。 請參閱: https : //docs.python.org/3.4/library/re.html
在郵件的標題中,您寫道:“從大型unicode文本文件中刪除符號”,因此我認為您要從文件中刪除一組字符。
要簡化符號集,您可以嘗試:
>>> symbols = "".join(frozenset(r'[{} &+( )" =!.?.:.. / | » © : >< # « ,] 1 2 3 4 5 6 7 8 9 _ - + ; [ ] %'))
>>> print(symbols)
! #"%&)(+-,/.132547698»:=<?>[];_|©{}«
這樣你就可以簡單地寫:
symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
讀者注意:這並不明顯,但這里的所有字符串都是unicode字符串。 我認為,作者使用Python 3.對於Python 2.7用戶,最好的方法是使用“utf8”編碼和
u""
語法,這樣:# -*- coding: utf8 -*- symbols = u'! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
或者,您可以導入unicode_literals,並刪除“u”前綴:
# -*- coding: utf8 -*- from __future__ import unicode_literals symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
如果要編寫與一個符號匹配的正則表達式,則必須轉義具有特殊含義的字符(例如:“[”應在“\\ [”中)轉義。 最好的方法是使用re.escape
函數。
>>> import re
>>> symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
>>> regex = "[{0}]".format(re.escape(symbols))
>>> print(regex)
[\!\ \#\"\%\&\)\(\+\-\,\/\.132547698\»\:\=\<\?\>\[\]\;\_\|\©\{\}\«]
試一試:
import re
symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
regex = "[{0}]+".format(re.escape(symbols))
example = '''" :621 " :621 :1 ;" _ " :594 :25 4 8 0 :23 "സര്ക്കാര്ജീവനക്കാരുടെ ശമ്പളം അറിയാന് ഭാര്യമാര്ക്ക് അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്
:621 :4 0 3 0 ;" _ " :551 :16 :3 "'''
print(re.sub(regex, "", example, re.UNICODE))
請注意,零不在符號集中但空間是,因此結果將是:
'''0സര്ക്കാര്ജീവനക്കാരുടെശമ്പളംഅറിയാന്ഭാര്യമാര്ക്ക്അവകാശമുണ്ട്വിവരാവകാശകമ്മീഷന്
00'''
我認為正確的符號集是: !#"%&)(+-,/.0132547698»:=<?>[];_|©{}«
。然后你可以去除每一行以刪除尾隨的空格。 。
因此,此代碼段應該適合您:
import re
symbols = '!#"%&)(+-,/.0132547698»:=<?>[];_|©{}«'
regex = "[{0}]+".format(re.escape(symbols))
sub_symbols = re.compile(regex, re.UNICODE).sub
with open('/home/corpus/All12.txt', 'a') as t:
with open('/home/corpus/All11.txt', 'r') as n:
data = n.readline()
data = sub_symbols("", data).strip()
t.write(data)
您是否考慮過解碼unicode,例如:
line = line.decode('utf_8')
然后重新編碼讓我們說... ascii而忽略它不知道的字符,例如:
line = line.encode('ascii', 'ignore')
不確定是更快還是更好。 正則表達式很慢,但我不知道這是更好的經驗。 這很容易;)
可能是O(2n)復雜度(組合),但長期正則表達式可能同樣糟糕。
更新:這是錯誤的,如下所述。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.