【问题标题】:Search for all words from a list for all files in directory, and return context从列表中搜索目录中所有文件的所有单词,并返回上下文
【发布时间】:2021-05-25 14:46:04
【问题描述】:

我有一个关键字列表

Animals = ['dogs' , 'cat' , 'bird' ....]

我有一个包含许多文件的目录,这些文件可能会出现 1 个或多个关键字。

文件1.txt

  • “我是一辆车,我去哔”
  • “我是猫,我去喵”
  • “我是一条狗,我会发疯”

文件2.txt

  • “我是一口铃铛”
  • “我是一只鸟,我去推特”
  • “我是打印机,我去 brrr”

我想搜索目录中的每个文件,并检查我的动物列表中的所有匹配项。 我要记录文件名、行号、匹配、行。

示例所需的输出:

  • File1.txt , 2 , cat , “我是猫,我喵喵”
  • File1.txt , 3 , dog, “我是条狗,我发疯了”
  • File2.txt , 2 , 鸟,“我是鸟,我去推特”

这可能吗? Python 是正确的工具吗? 我已经能够使用 python 运行一些正则表达式测试,但我无法访问特定的 行号、匹配和行。

import os
import re

words = ['dog' , 'cat' , 'bird' ]

rx = re.compile('|'.join(words), re.I)

for root, dirs, files in os.walk('C:\\MySearchDirectory\\'):
    for filename in files:
        if filename.endswith('.txt'):
            with open(root + filename) as df:
                data = df.read()
                for match in rx.finditer(data):
                    print(filename + ' , ' + str(match) + ' , ' + str(match.span()))

【问题讨论】:

  • 不确定最好的方法是什么,因为我不喜欢正则表达式,但你绝对应该使用glob 而不是os 来获取文件名,因为它会更短。 list_of_text_files = glob.glob('C:\\MySearchDirectory\\*.txt')
  • glob 也是内置的,所以你应该拥有它
  • 您好,感谢您的评论,我将尝试使用 glob 重新编写代码,我在搜索此内容时看到了一些关于此的内容。如果我不使用正则表达式,我担心我只会强行搜索。所以对于我 wordSearch 列表中的每个元素,我会检查每个文件中的每一行。
  • 正则表达式仍在检查每个文件中的每一行;没有办法逃脱(除了使用数据库而不是平面文件)。

标签: python list


【解决方案1】:

当 Python 的标准 in 运算符可以完成这项工作时,无需使用正则表达式,IMO:

import os

words = ['dog', 'cat', 'bird']

for root, _, files in os.walk(r'C:\MySearchDirectory'):
    for path in filter(lambda p: p.endswith('.txt'), files):
        with open(os.path.join(root, path)) as f:
            for i, line in enumerate(f.readlines()):
                for word in filter(lambda w: w in line, words):
                    print(f'{path}, {i+1}, {word}, {line.strip()}')

在循环中使用filter 与列表理解与if 是一个口味问题,但在这种情况下,我认为这是最直接的选择,因为它产生了两个过滤条件(文件需要以@ 结尾987654325@,需要在行中出现单词)一目了然。

输出:

File1.txt, 2, cat, "I'm a cat, I go meow"
File1.txt, 3, dog, "I'm a dog, I go woof"
File2.txt, 2, bird, "I'm a bird, I go tweet"

【讨论】:

  • 哇 samwise,谢谢。哇,这真是太神奇了。我需要一些时间来理解所有的部分,但这正是我想要的。这非常有用。
【解决方案2】:

你可以这样做:

from pathlib import Path

def find_occurrences(file, any_word:list) -> list:
    occurrences = []
    with open(file, 'r') as f:
        text = f.read()
        lines = text.split('\n')
        for line_number, line in enumerate(lines, start=1):
            matched_words = [word for word in any_word if word in line]
            if matched_words:
                occurrence = {
                    "file": file, 
                    "line_number": line_number, 
                    "line": line, 
                    "matched_words": matched_words
                }
                occurrences.append(occurrence)
    return occurrences

occurrences = []
for file in Path(r"C:\\MySearchDirectory\\").glob("**/*.txt"):
    occurrences += find_occurrences(file, any_word=["cat", "dog"])
occurrences

首先我们循环目录中的所有“.txt”文件,并为每个文件执行函数find_occurrences。这个函数返回出现的列表,我们用它来更新我们的最终结果。该函数本身只读取一个文件,遍历文件的每一行,检查每一行是否包含指定的单词,如果包含则存储到结果中。

返回的字典列表结构如下:

[
    {
        'file': 'C:\\MySearchDirectory\\subdir\\file1.txt', 
        'line_number': 5, 
        'matched_words': ['cat', 'dog'], 
        'line': 'meau cat, hau hau dog'
    }, 
    ...
]

如果您需要额外的东西,只需调整出现字典。请注意 line_number 从一开始。这似乎是示例中的意图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 2011-12-17
    相关资源
    最近更新 更多