Skip to main content
 首页 » 编程设计

python之如何对正则表达式中的某些单词进行异常(exception)处理

2025年05月04日27linjiqin

我是编程和正则表达式方面的新手,如果之前有人问过这个问题,我深表歉意(不过我没有找到)。

我想使用 Python 来汇总文字文本中的词频。假设文本的格式类似于

Chapter 1 
blah blah blah 
 
Chapter 2 
blah blah blah 
.... 

现在我将文本作为字符串读取,我想使用re.findall 来获取这段文本中的每个单词,所以我的代码是

wordlist = re.findall(r'\b\w+\b', text) 

但问题是它与每个章节标题中的所有这些 Chapter 匹配,我不想将其包含在我的统计信息中。所以我想忽略匹配 Chapter\s*\d+ 的内容。我该怎么办?

在此先感谢各位。

请您参考如下方法:

解决方案

您可以先删除所有 Chapter+space+digits :

wordlist = re.findall(r'\b\w+\b', re.sub(r'Chapter\s*\d+\s*','',text)) 

如果您只想使用一次搜索,您可以使用否定先行查找前面没有“第 X 章”且不以数字开头的任何单词:

wordlist = re.findall(r'\b(?!Chapter\s+\d+)[A-Za-z]\w*\b',text) 

如果性能是个问题,加载一个巨大的字符串并用 Regex 解析它无论如何都不是正确的方法。只需逐行读取文件,抛出任何匹配 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 秒,并且使用的内存并不比其他脚本少多少。如果您对如何改进脚本有任何想法,请发表评论!