【问题标题】:Alternative way to extract lines from text (python-regex)从文本中提取行的替代方法(python-regex)
【发布时间】:2013-06-27 10:26:53
【问题描述】:

我正在寻找一种从 python 中相当大的数据库中提取行的方法。我只需要保留那些包含我的关键字之一。 我想我可以使用正则表达式来解决这个问题,我把下面的代码放在一起。不幸的是,它给了我一些错误(可能也是因为我的关键字,它们分别写在文件 listtosearch.txt 中的单独行中,确实数量很大,接近 500 个)。

import re
data = open('database.txt').read() 
fileout = open("fileout.txt","w+")

with open('listtosearch.txt', 'r') as f:
    keywords = [line.strip() for line in f]

pattern = re.compile('|'.join(keywords))

for line in data:
    if pattern.search(line):
        fileout.write(line)

我也尝试过使用双循环(在关键字列表和数据库行中),但运行时间太长。

我得到的错误是:

Traceback (most recent call last):
  File "/usr/lib/python2.7/re.py", line 190, in compile 
    return _compile(pattern, flags)   
  File "/usr/lib/python2.7/re.py", line 240, in _compile 
    p = sre_compile.compile(pattern, flags) 
  File "/usr/lib/python2.7/sre_compile.py", line 511, in compile 
    "sorry, but this version only supports 100 named groups" 
AssertionError: sorry, but this version only supports 100 named groups

有什么建议吗?谢谢

【问题讨论】:

  • 它给了我这些错误:pattern = re.compile('|'.join(keywords)) File "/usr/lib/python2.7/re.py", line 190, in compile return _compile(pattern, flags) File "/usr/lib/python2.7/re.py", line 240, in _compile p = sre_compile.compile(pattern, flags) File "/usr/lib/python2.7/sre_compile .py", line 511, in compile "sorry, but this version only support 100 named groups" AssertionError: sorry, but this version only support 100 named groups
  • 好了,它告诉您正则表达式模式中的子表达式不能超过 100 个。不是你的错。布莱斯的回答会奏效。
  • 实际上,即使我运行 Brice 的代码,它也会给我完全相同的错误:(
  • @user2447387 这是不可能的。我的代码没有使用 re 模块,而且我没有违规行。
  • 我知道,对不起,我的错!让我正常运行

标签: python regex text


【解决方案1】:

您可能想看看Aho–Corasick string matching algorithm。可以在 here 找到一个在 python 中工作的实现。

这个模块的一个简单示例用法:

from pyahocorasick import Trie

words = ['foo', 'bar']

t = Trie()
for w in words:
    t.add_word(w, w)
t.make_automaton()

print [a for a in t.iter('my foo is a bar')]

>> [(5, ['foo']), (14, ['bar'])]

在您的代码中集成应该很简单。

【讨论】:

  • 我会看看,谢谢,但是考虑到我对 python 和一般编码的有限概念,这似乎相当困难:(
【解决方案2】:

这是我的代码:

import re
data = open('database.txt', 'r')
fileout = open("fileout.txt","w+")

with open('listtosearch.txt', 'r') as f:
    keywords = [line.strip() for line in f]

# one big pattern can take time to match, so you have a list of them
patterns = [re.compile(keyword) for keyword in keywords]

for line in data:

    for pattern in patterns:
        if not pattern.search(line):
            break
    else:
        fileout.write(line)

我用以下文件对其进行了测试:

数据库.txt

"Name jhon" (1995)
"Name foo" (2000)
"Name fake" (3000)
"Name george" (2000)
"Name george" (2500)

listtosearch.txt

"Name (george)"
\(2000\)

这就是我在 fileout.txt 中得到的内容

"Name george" (2000)

所以这也应该在你的机器上工作。

【讨论】:

  • 我不知道为什么(对不起,我是python的初学者)但是这样没有提取任何行
  • 关键字是这样的形式:“姓名姓名”(年份)并且必须完全匹配(“”中的姓名和括号中的年份)
  • 你用的是什么版本的 Python?
  • 然后你可以只用一个 in 就可以在线循环了(就像你已经在阅读关键字一样,我没有注意到)。我修改了 sn-p 以确保所有正则表达式都匹配。
  • :( 输出文件结果又是空的......我真的不知道为什么
【解决方案3】:

首先,我很确定您指的是 data = open('database.txt').readlines() 而不是 read()。否则,data 将是一个字符串而不是行列表,而您的 for line in data 将没有任何意义。

此时,您实际上是在寻找按关键字建立索引的解决方案,而幼稚的搜索将不再有效地为您提供及时的结果。

确实没有其他方法比它更有效或更简单。您将不得不磨牙并接受查看整个数据库的成本。

另外,如果你的数据库完全适合内存,它就不可能那么大:)

也就是说,还有其他可能会更有效的方法:

  1. 将你的关键词放在一个集合中,然后将输入数据标记为单词并在集合中查找所有这些:

    data = open('database.txt').readlines() 
    fileout = open("fileout.txt","w+")
    
    with open('listtosearch.txt', 'r') as f:
      keywords = [line.strip() for line in f]
    
    keywords = set(keywords)
    
    for line in data:
        # You might have to be smarter about splitting the line to 
        # take things like punctuation into consideration.
        for word in line.split():
          if word in keywords:
            fileout.write(line)
            break
    

    Here 是一个考虑标点符号的分词示例。

【讨论】:

  • 我不知道为什么(对不起,我是python的初学者)但是这样没有提取任何行。我的关键字采用这种形式:“姓名”(年份),并且必须完全匹配才能提取一行。
【解决方案4】:

可能不是一个有效的解决方案,但尝试使用 set 和它的交集属性。

from_db = tuple([line.rstrip("\n") for line in open('database.txt') if line.rstrip('\n')])
keywords = set([line.rstrip("\n") for line in open('listtosearch.txt') if line.rstrip('\n')])
with open("output_file.txt", "w") as fp:
    for line in from_db:
        line_set = set(line.split(" "))
        if line_set.intersection(keywords):
            fp.write(line + "\n")

Intersection 将检查任何常见的字符串。由于比较了哈希值,我想搜索会更快,而不是一次又一次地遍历整个列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多