Вопрос:
Я хочу, чтобы пользователь выбирал и открывал несколько текстов и выполнял поиск точных совпадений в текстах. Я хочу, чтобы кодировка была unicode.
Если я ищу “кот”, я хочу, чтобы он нашел “cat”, “cat”, “.cat”, но не “каталог”.
Я не знаю, как позволить пользователю искать два слова (“кошка” или “собака”) во всех текстах одновременно????? Может быть, я могу использовать RE?
До сих пор я только что дал пользователю возможность вставить путь в каталог, содержащий текстовые файлы для поиска. Теперь я хочу, чтобы пользователь (raw_input) искал два слова во всех текстах, а затем печатал и сохраните результаты (например, “search_word_1” и “search_word_2”, найденные в файле document1.txt, “search_word_2”, найденные в документе4.txt) в отдельном документе (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() Лучший ответ:
В этом случае регулярные выражения являются подходящим инструментом.
Я хочу, чтобы он нашел “cat”, “cat”, “.cat”, но не “каталог”.
Выкройка: r’bcatb’
b соответствует границе слова.
как разрешить пользователю искать два слова (“кошка” или “собака”) во всех текстах одновременно
Выкройка: r’bcatb|bdogb’
Чтобы напечатать «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%sb» % 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%sb» % 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 Ответ №1
Вам нужно разделить текст в каждом файле на пробелы и пунктуацию. После этого вы можете просто искать слова, которые ищете в остальном списке. Вам также нужно преобразовать все в нижний регистр, если вы также не хотите, чтобы поиск с учетом регистра.
Ответ №2
Некоторая (возможно полезная) информация в дополнение к существующим ответам:
Вы должны знать, что то, что пользователь означает, когда он думает о “характере” (= grapheme), не всегда совпадает с символом Unicode, а некоторые графемы могут быть представлены символами Unicode более чем одним уникальным способом (например, составной символ против базового символа + комбинация метки).
Чтобы выполнить поиск на основе графем (= то, чего ожидает пользователь в большинстве случаев), а не для определенных последовательностей символов Unicode, вам необходимо нормализовать строки перед тем, как искать.