2

为了文本规范化,我希望能够跨文档进行大规模搜索和替换。

例如:

  1. 查找USA , USA的所有用途并替换为United States Of America
  2. 查找所有与号 (&) 并替换为单词and

我还希望能够在不更改任何代码的情况下向系统添加新规则。因此搜索替换对存储在数据存储中,这意味着任何人都可以添加、更新、删除规则。

我一直在使用 Python re 模块,它非常好,理想情况下,我想将一个元组列表传递给子命令,然后遍历每一个并进行替换。除了遍历元组列表然后为每个元组创建一个正则表达式之外,是否有更好的方法来做到这一点 - 它非常缓慢且效率低下,尤其是对于大型文档:

replacements = [
  r('USA','United States Of America'),
  (r'U\.S\.A','United States Of America'),
  (r'US of A', 'United States of America')]

for replacement in replacements:
  document = re.sub(replacement[0],replacement[1],document
4

3 回答 3

1

您的示例都不需要正则表达式。为什么不尝试好的 ol' 字符串替换?

replacements = [
    ('USA','United States Of America'),
    ('U\.S\.A','United States Of America'),
    ('US of A', 'United States of America')]

for replacement in replacements:
    document = document.replace(replacement[0], replacement[1])

这似乎会很慢,但是您应该在排除该方法之前对其进行基准测试。Python 非常擅长这样的事情,结果可能会让你大吃一惊。

如果你真的需要正则表达式,你可能会通过编译它们看到巨大的提升:

replacements = [
    (re.compile('USA'),'United States Of America'),
    (re.compile('U\.S\.A'),'United States Of America'),
    (re.compile('US of A'), 'United States of America')]

for pattern, replacement in replacements:
    document = pattern.sub(replacement, document)

这节省了 Python 每次使用它们时都必须重新编译这些正则表达式的工作。

如果您有时只需要正则表达式,请考虑对文档进行两次传递:一次使用正则表达式,一次使用字符串替换。或者,如果您需要一些特定的替换顺序,您可以使用以下内容:

replacements = [
    (re.compile('USA'),'United States Of America'),
    ('foo', 'bar'),
    (re.compile('U\.S\.A'),'United States Of America'),
    ('spam', 'eggs'),
    (re.compile('US of A'), 'United States of America')]

for pattern, replacement in replacements:
    try:
        document = pattern.sub(replacement, document)
    except AttributeError:
        document = document.replace(pattern, replacement)
于 2012-05-22T15:00:04.930 回答
0

我有一个包含 6 MB 文本的大屁股文件。它是几个 Project Gutenberg 文件的汇编。

试试这个:

reps = [
  (r'\bthousand\b','>>>>>1,000<<<<<'),
  (r'\bmillion\b',">>>>>1e6<<<<<"),
  (r'\b[Hh]undreds\b',">>>>>100's<<<<<"),
  (r'\bSherlock\b', ">>>> SHERLOCK <<<<")
  ]

t1=time.time()
out=[]  
rsMade=0
textLength=0
NewTextLen=0
with open('big.txt') as BigAssF:
    for line in BigAssF:
        textLength+=len(line)
        for pat, rep in reps:
            NewLine=re.subn(pat,rep,line)     

        out.append(NewLine[0])
        NewTextLen+=len(NewLine[0])
        rsMade+=NewLine[1]

print 'Text Length: {:,} characters'.format(textLength)
print 'New Text Length: {:,} characters'.format(NewTextLen)     
print 'Replacements Made: {}'.format(rsMade)     
print 'took {:.4} seconds'.format(time.time()-t1) 

它打印:

Text Length: 6,488,666 characters
New Text Length: 6,489,626 characters
Replacements Made: 96
took 2.22 seconds

这对我来说似乎足够快。

您的代码行可能存在一些问题:

document = re.sub(replacement[0],replacement[1],document

如果那不是错字。

你期望它有多快?

于 2012-05-22T17:15:03.837 回答
0

看看谷歌优化。

Google Refine,用于处理杂乱数据的强大工具

http://code.google.com/p/google-refine/

于 2012-05-22T14:54:49.473 回答