Python 从目录中所有文件的列表中搜索所有单词,并返回上下文

Python 从目录中所有文件的列表中搜索所有单词,并返回上下文,python,list,Python,List,我有一个关键字列表 Animals = ['dogs' , 'cat' , 'bird' ....] 我有一个包含许多文件的目录,其中可能出现1个或多个关键字 File1.txt “我是一辆车,我去嘟嘟” “我是一只猫,我会喵喵叫” “我是一条狗,我去求爱” File2.txt “我是一只铃铛,我去叮当” “我是一只鸟,我去推特” “我是打印机,我去brrr” 我想搜索目录中的每个文件,并检查我的动物列表中的所有事件。 我想记录文件名、行号、匹配项、行 所需输出示例: File1.t

我有一个关键字列表

Animals = ['dogs' , 'cat' , 'bird' ....]
我有一个包含许多文件的目录,其中可能出现1个或多个关键字

File1.txt

  • “我是一辆车,我去嘟嘟”
  • “我是一只猫,我会喵喵叫”
  • “我是一条狗,我去求爱”
File2.txt

  • “我是一只铃铛,我去叮当”
  • “我是一只鸟,我去推特”
  • “我是打印机,我去brrr”
我想搜索目录中的每个文件,并检查我的动物列表中的所有事件。 我想记录文件名、行号、匹配项、行

所需输出示例:

  • File1.txt,2,cat,“我是一只猫,我会喵喵叫”
  • File1.txt,3,dog,“我是一只狗,我去求爱”
  • File2.txt,2,bird,“我是一只鸟,我去推特”
这可能吗?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()))

当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
vs列表理解vs
if
是一个趣味问题,但在这种情况下,我认为这是最简单的选择,因为它使两个过滤条件(文件需要以
.txt
结尾,单词需要出现在行中)一目了然

输出:

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"

当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
vs列表理解vs
if
是一个趣味问题,但在这种情况下,我认为这是最简单的选择,因为它使两个过滤条件(文件需要以
.txt
结尾,单词需要出现在行中)一目了然

输出:

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"
您可以这样做:

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\u occurrencess
。这个函数返回事件列表,我们用它更新最终结果。函数本身只读取一个文件,遍历文件的每一行,检查每一行是否包含指定的单词,如果包含指定的单词,则存储到结果中

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

[
    {
        'file': 'C:\\MySearchDirectory\\subdir\\file1.txt', 
        'line_number': 5, 
        'matched_words': ['cat', 'dog'], 
        'line': 'meau cat, hau hau dog'
    }, 
    ...
]
如果您需要其他内容,只需调整事件字典即可。请注意,行_编号从1开始。这似乎是本例的目的。

您可以按以下方式执行:

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\u occurrencess
。这个函数返回事件列表,我们用它更新最终结果。函数本身只读取一个文件,遍历文件的每一行,检查每一行是否包含指定的单词,如果包含指定的单词,则存储到结果中

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

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

如果您需要其他内容,只需调整事件字典即可。请注意,行_编号从1开始。这似乎是本例的意图。

不确定最好的方法是什么,因为我不喜欢正则表达式,但您肯定应该使用
glob
over
os
来获取文件名,因为它会短得多
list\u of_text\u files=glob.glob('C:\\MySearchDirectory\\*.txt')
glob
也是内置的,所以你应该知道。谢谢你的评论,我会尝试用glob重新编写代码,我在搜索时看到了一些关于这方面的东西。如果我不使用正则表达式,我担心我会粗暴地强迫搜索。因此,对于wordSearch列表中的每一个元素,我都要检查每个文件中的每一行;没有办法逃避这个问题(除了使用数据库而不是平面文件)。我不确定这样做的最佳方式是什么,因为我不喜欢正则表达式,但您肯定应该使用
glob
over
os
来获得文件名,因为它会短得多
list\u of_text\u files=glob.glob('C:\\MySearchDirectory\\*.txt')
glob
也是内置的,所以你应该知道。谢谢你的评论,我会尝试用glob重新编写代码,我在搜索时看到了一些关于这方面的东西。如果我不使用正则表达式,我担心我会粗暴地强迫搜索。因此,对于wordSearch列表中的每一个元素,我都要检查每个文件中的每一行;这是无法逃避的(除了使用数据库而不是平面文件)。哇,这真是太棒了。我需要一些时间来理解所有的片段,但这正是我想要的。这真是太有用了。哇,桑怀斯,谢谢你。哇,这真是太棒了。我需要一些时间来理解所有的片段,但这正是我想要的。这是非常有用的。