我有一个文本文件,其中包含大约调整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 "
=' 'ന്യൂഡല്ഹി: സര്ക്കാര്ജീവനക്കാരായ ഭര്ത്താക്കന്മാരുടെ ശമ്പളം
欲望输出为ന്യൂഡല്ഹി സര്ക്കാര്ജീവനക്കാരായ ഭര്ത്താക്കന്മാരുടെ ശമ്പളം
。
代码无法正常运行。它会停止我的电脑。
我可以用正则表达式来解决这个问题吗?
答案 0 :(得分:2)
您需要在方括号[]
中插入要替换的每个符号,转义一些特殊符号,例如[]
本身,单引号'
和\
。正则表达式是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()
答案 1 :(得分:1)
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
中列出您要删除的符号。
或者,您可以使用字符块读取文件,这比单独读取超过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))
答案 2 :(得分:0)
第一个[和]之间的符号列表之后的重新对我没有意义。它不会剥离符号,但只会删除一个符号后跟'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:
答案 3 :(得分:0)
[{} &+( )" =!.?.:.. / | » © : >< # « , 1 2 3 4 5 6 7 8 9 _ - + ; \[ \] %]
试试这个。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)
答案 4 :(得分:0)
解决方案没有REGEX:
您可以使用地图功能以及要删除的一组符号来完成此操作。
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"'
答案 5 :(得分:0)
我认为你的正则表达式不正确,因为你可以简化它。
例如,子表达式[{} &+( )" =!.?.:.. / | » © : >< # « ,]
可以简化
在[ !"#&()+,./:<=>?{|}©«»]
中:只保留每个角色一次。
这是因为[]
用于表示一组字符。
看看章节&#34;正则表达式操作&#34;在Python文档中。
请参阅:https://docs.python.org/3.4/library/re.html
在邮件的标题中,您写道:&#34;从大型unicode文本文件中删除符号&#34;, 所以我认为您要从文件中删除一组字符。
要简化符号集,您可以尝试:
>>> symbols = "".join(frozenset(r'[{} &+( )" =!.?.:.. / | » © : >< # « ,] 1 2 3 4 5 6 7 8 9 _ - + ; [ ] %'))
>>> print(symbols)
! #"%&)(+-,/.132547698»:=<?>[];_|©{}«
这样你就可以简单地写:
symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
读者注意:这不明显,但这里的所有字符串都是unicode字符串。 我认为,作者使用Python 3。 对于Python 2.7用户,最好的方法是使用&#34; utf8&#34;编码和
u""
语法,这样:# -*- coding: utf8 -*- symbols = u'! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
或者,您可以导入unicode_literals,然后删除&#34; u&#34;前缀:
# -*- coding: utf8 -*- from __future__ import unicode_literals symbols = '! #"%&)(+-,/.132547698»:=<?>[];_|©{}«'
如果要编写与一个符号匹配的正则表达式,则必须转义字符
具有特殊含义(例如:&#34; [&#34;应该在&#34; \ [&#34;中)进行转义。
最好的方法是使用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)
答案 6 :(得分:0)
您是否考虑过解码unicode,例如:
line = line.decode('utf_8')
然后重新编码让我们说... ascii而忽略了它不知道的字符,如:
line = line.encode('ascii', 'ignore')
不确定是更快还是更好。正则表达式很慢,但我不能凭经验知道这更好。这很容易;)
可能是O(2n)的复杂性(合并),但长期正则表达可能同样糟糕。
更新:这是错误的,如下所述。