2010-06-09 81 views
3

基本上是问题状态。我对Python相当陌生,喜欢通过看和做来学习。使用Python搜索一个.txt文件以获得单词或短语列表(并显示上下文)

我想要创建一个脚本来搜索文本文档(比如从新闻文章中复制和粘贴的文本)以查找某些单词或短语。理想情况下,单词和短语的列表将存储在一个单独的文件中。

当获得结果时,获得结果的上下文将是非常好的。所以也许它可以在找到的每个搜索词前后在文本文件中打印出50个字符。如果它也显示搜索词的搜索结果,它会很酷。

任何关于如何编码的指针,甚至代码示例都将不胜感激。

+0

您的功课? ;) – Aivar 2013-01-18 20:37:37

回答

3

从这样的事情开始。此代码并不是您所具有的规范的完全解决方案,但它是一个很好的起点。

import sys 

words = "foo bar baz frob" 

word_set = set(words.split()) 
for line_number, line in enumerate(open(sys.argv[1])): 
    if words_set.intersection(line.split()): 
     print "%d:%s" % (line_number, line.strip()) 

下面几点说明:

  • 正在寻求被存储在一个字符串最初(第3行)的话。我沿着空格分隔这个单词列表并创建一个列表,以便检查是否在单词列表中找到当前行中的任何单词。 (在一个集合上的成员资格检查是O(1),而在列表上是O(n))。

  • 在主for循环中,我打开输入文件(作为命令行参数传递),并使用内置方法获取行号计数器以及实际行。 sys.argv是存储命令行参数的数组; sys.argv[0]始终是Python脚本的名称。

  • 在循环本身中,我采用当前行,将其拆分为单个单词并再次创建单词集。然后,我可以快速将当前行中的单词集与我正在查找的单词集相交。如果交叉点具有逻辑值True(即,如果它不是空的),则我打印行号以及行。

的东西都没有解决(留给了你):

  • 单词列表现在硬编码在源代码,但它不应该太难开一个额外的文件(其名称被传入,例如sys.argv[2]),逐个读取它的文字并将它们存储在一个集合中。请注意,您可以通过它们的addupdate方法扩展集(而不是用于列表的appendextend)。

  • 显然,如果您有词组而不是单词(如其中一个注释中指出的那样),上述方法不起作用。因为我假设你想学习,并且你不需要一个确切的解决方案,所以我只会说,如果你在一个集合中有短语,你可以通过说any(phrase in line for phrase in set_of_phrases)来检查是否有任何集合元素在一行中。这可以用来代替设定的交集(当然,在这种情况下不要将您的行分成单词)。

  • 如果要打印命中的上下文,可以使用两个额外的变量(比如说,prev_linenext_line),它存储上一行和下一行。在for循环中,实际上您将读取的是next_line而不是line,并且在for循环结束时,应该注意将line复制到prev_linenext_line中,复制到line中。

  • 一个甚至更Python跟踪先前的和下一个线以及的方式是创建一个产生由项目的元组一个Python发生器功能的i-1,项目和项目我+1每个i给定一个可迭代(如文件)。不过,这是更高级的东西,因为对于Python来说相当陌生,所以我认为最好先留下来。但是,如果你很好奇,生成函数完成这个任务可能是这样的:

    def context_generator(iterable): 
        prev, current, next = None, None, None 
        for element in iterable: 
         prev, current, next = current, next, element 
         if current is not None: 
          yield prev, current, next 
        if next is not None: 
         yield current, next, None 
    
+0

*打开输入文件*你需要使用'open'。 – SilentGhost 2010-06-09 17:17:56

+0

当然,我的不好,谢谢。 – 2010-06-09 17:21:00

+0

这也不适用于短语,只是单个单词。 – FogleBird 2010-06-09 17:22:51

6

尽管对许多Python社区的一部分正则表达式经常表示反感,他们真的很一个用于适当用例的宝贵工具 - 这肯定包括识别单词和短语(由于正则表达式模式中的“单词边界”元素 - 基于字符串处理的替代方法更加成为一个问题,例如,.split()使用空格作为分隔符,因此烦人地将标点符号附加到它旁边的单词等等)。

如果RE的都OK,我建议是这样的:

import re 
import sys 

def main(): 
    if len(sys.argv) != 3: 
    print("Usage: %s fileofstufftofind filetofinditin" % sys.argv[0]) 
    sys.exit(1) 

    with open(sys.argv[1]) as f: 
    patterns = [r'\b%s\b' % re.escape(s.strip()) for s in f] 
    there = re.compile('|'.join(patterns)) 

    with open(sys.argv[2]) as f: 
    for i, s in enumerate(f): 
     if there.search(s): 
     print("Line %s: %r" % (i, s)) 

main() 

的第一个参数是(路径)用的词或短语的文本文件发现,每行一个,第二个参数( )在其中找到它们的文本文件的路径。这很容易,如果需要的话,使病例检索不敏感(也许只是基于可选命令行选项开关),等等,等等

一些解释读者不熟悉的RE ...:

patterns项目中的\b项目确保不会发生意外匹配(如果您正在搜索“猫”或“狗”,您将不会看到“目录”或“失败者”的意外击中;并且你不会错过“猫,微笑,逃跑”中的一击,它被一些分裂的思想认为有“猫”这个词,包括逗号;-)。

|项意味着or,例如,从内容的文本文件(两行)

cat 
dog 

这将形成较长的单词中的模式'\bcat\b|\bdog\b'将定位要么“猫”和“狗”(作为独立的话,忽略标点符号,但拒绝命中)。

re.escape转义标点符号,所以它的字面匹配,而不是像它通常在RE模式中具有的特殊含义。

+0

再一次,感谢您的答复 - 一些代码与解释是非常有帮助的。我曾想过关于RE,但不知道在这种情况下它是否相关 - 很高兴看到它! – prupert 2010-06-10 07:47:35

相关问题