解决方案
您可以先删除所有Chapter+space+digits:
wordlist = re.findall(r'\b\w+\b', re.sub(r'Chapter\s*\d+\s*','',text))
如果您只想使用一次搜索,您可以使用否定前瞻来查找前面没有“Chapter X”且不以数字开头的任何单词:
wordlist = re.findall(r'\b(?!Chapter\s+\d+)[A-Za-z]\w*\b',text)
如果性能是一个问题,加载一个巨大的字符串并使用正则表达式解析它无论如何都不是正确的方法。只需逐行读取文件,丢弃任何与r'^Chapter\s*\d+' 匹配的行,然后用r'\b\w+\b' 分别解析剩余的每一行:
import re
lines=open("huge_file.txt", "r").readlines()
wordlist = []
chapter = re.compile(r'^Chapter\s*\d+')
words = re.compile(r'\b\w+\b')
for line in lines:
if not chapter.match(line):
wordlist.extend(words.findall(line))
print len(wordlist)
性能
我写了一个小的 ruby 脚本来写一个大文件:
all_dicts = Dir["/usr/share/dict/*"].map{|dict|
File.readlines(dict)
}.flatten
File.open('huge_file.txt','w+') do |txt|
newline=true
txt.puts "Chapter #{rand(1000)}"
50_000_000.times do
if rand<0.05
txt.puts
txt.puts
txt.puts "Chapter #{rand(1000)}"
newline = true
end
txt.write " " unless newline
newline = false
txt.write all_dicts.sample.chomp
if rand<0.10
txt.puts
newline = true
end
end
end
生成的文件有超过 5000 万字,大小约为 483MB:
Chapter 154
schoolyard trashcan's holly's continuations
Chapter 814
assure sect's Trippe's bisexuality inexperience
Dumbledore's cafeteria's rubdown hamlet Xi'an guillotine tract concave afflicts amenity hurriedly whistled
Carranza
loudest cloudburst's
Chapter 142
spender's
vests
Ladoga
Chapter 896
petition's Vijayawada Lila faucets
addendum Monticello swiftness's plunder's outrage Lenny tractor figure astrakhan etiology's
coffeehouse erroneously Max platinum's catbird succumbed nonetheless Nissan Yankees solicitor turmeric's regenerate foulness firefight
spyglass
disembarkation athletics drumsticks Dewey's clematises tightness tepid kaleidoscope Sadducee Cheerios's
两步过程提取词表平均需要 12.2 秒,前瞻方法需要 13.5 秒,而 Wiktor 的回答也需要 13.5 秒。我最开始写的lookahead方法使用了re.IGNORECASE,耗时18s左右。
读取整个文件时,所有Regexen方法的性能基本没有差异。
但令我惊讶的是,readlines 脚本花费了大约 20.5 秒,并且使用的内存并没有比其他脚本少多少。如果您有任何想法如何改进脚本,请发表评论!