【问题标题】:Search for words (exact matches) in multiple texts using Python使用 Python 在多个文本中搜索单词(完全匹配)
【发布时间】:2012-12-27 11:04:54
【问题描述】:

我想让用户选择并打开多个文本并在文本中搜索完全匹配的内容。 我希望编码是 unicode。

如果我搜索“cat”,我希望它找到“cat”、“cat”、“.cat”,而不是“catalogue”。

我不知道如何让用户在所有文本中同时搜索两个词(“猫”或“狗”)?????? 也许我可以使用 RE?

到目前为止,我刚刚使用户可以插入包含要搜索的文本文件的目录的路径。现在我想让用户 (raw_input) 在所有文本中搜索两个单词,并且然后将结果(例如 document1.txt 中的“search_word_1”和“search_word_2”,document4.txt 中的“search_word_2”)打印并保存在单独的文档 (search_words) 中。

import re, os


path = raw_input("insert path to directory :")
ex_library = os.listdir(path)
search_words = open("sword.txt", "w") # File or maybe list to put in the results
thelist = []

for texts in ex_library:
    f = os.path.join(path, texts)
    text = open(f, "r")
    textname = os.path.basename(texts)
    print textname
    for line in text.read():

    text.close()

【问题讨论】:

  • 你得到了什么?你期待什么?
  • for names in textname.split(): 只会为您提供文件基本名称中的字符列表。您需要将其更改为:for line in text.read():,然后您将遍历文本文件中的行。
  • 不要使用file作为变量名。
  • @BurhanKhalid:可以使用file 作为变量名。 Python 3 中没有内置 file。您应该始终使用 open 而不是 file 打开文件。需要创建file 的子类的情况很少见。
  • 这是一个非常简单的python递归grep版本:gist.github.com/4387573

标签: python regex search


【解决方案1】:

在这种情况下,正则表达式是合适的工具。

我希望它找到“cat”、“cat”、“.cat”,而不是“catalogue”。

模式:r'\bcat\b'

\b 匹配单词边界。

如何让用户在所有文本中同时搜索两个词(“猫”或“狗”)

模式:r'\bcat\b|\bdog\b'

打印"filename: <words that are found in it>":

#!/usr/bin/env python
import os
import re
import sys

def fgrep(words, filenames, encoding='utf-8', case_insensitive=False):
    findwords = re.compile("|".join(r"\b%s\b" % re.escape(w) for w in words),
                           flags=re.I if case_insensitive else 0).findall
    for name in filenames:
        with open(name, 'rb') as file:
             text = file.read().decode(encoding)
             found_words = set(findwords(text))
             yield name, found_words

def main():
    words = [w.decode(sys.stdin.encoding) for w in sys.argv[1].split(",")]
    filenames = sys.argv[2:] # the rest is filenames
    for filename, found_words in fgrep(words, filenames):
        print "%s: %s" % (os.path.basename(filename), ",".join(found_words))

main()

例子:

$ python findwords.py 'cat,dog' /path/to/*.txt

替代解决方案

为了避免读取内存中的整个文件:

import codecs

...
with codecs.open(name, encoding=encoding) as file:
    found_words = set(w for line in file for w in findwords(line))

您还可以在找到的上下文中打印找到的单词,例如,打印带有突出显示的单词的行:

from colorama import init  # pip install colorama
init(strip=not sys.stdout.isatty())  # strip colors if stdout is redirected
from termcolor import colored  # pip install termcolor

highlight = lambda s: colored(s, on_color='on_red', attrs=['bold', 'reverse'])

...
regex = re.compile("|".join(r"\b%s\b" % re.escape(w) for w in words),
                   flags=re.I if case_insensitive else 0)

for line in file:
    if regex.search(line): # line contains words
       line = regex.sub(lambda m: highlight(m.group()), line)
       yield line

【讨论】:

  • 非常感谢。这很有帮助。我了解第一个示例中的大部分内容,但我对区分大小写感到困惑。我已经尝试过了,当我搜索“cat”时,它会找到“cat”而不是“Cat”
  • 也许我只需要输入 True 而不是 False? def fgrep(words, filenames, encoding='utf-8', case_insensitive=True):
  • @user1921937:调用时在 main 中提供参数:for filename, found_words in fgrep(words, filenames, case_insensitive=True): ...
【解决方案2】:

您需要将每个文件中的文本拆分为空格和标点符号。完成后,您只需在剩余列表中查找要搜索的单词。您还需要将所有内容都转换为小写,除非您还需要区分大小写的搜索。

【讨论】:

    【解决方案3】:

    除了现有答案之外的一些(可能有用的)信息:

    您应该知道,当用户想到“字符”(=grapheme)时,他的意思并不总是与 Unicode 字符相同,并且某些字素可以通过 Unicode 字符以不止一种独特的方式表示(例如复合字符与基本字符 + 组合标记)。

    要基于字形(=用户在大多数情况下的期望)而不是特定的 Unicode 字符序列进行搜索,您需要在搜索前normalize您的字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-14
      • 2023-01-02
      • 2019-09-22
      • 2011-11-30
      • 2015-07-25
      相关资源
      最近更新 更多