繁体   English   中英

从大型unicode文本文件中删除符号

[英]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.translatestr.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM