Подсчет количества совпадений регулярного выражения в нескольких папках

#python #regex

Вопрос:

Я недавно начал использовать python3, и у меня возникли некоторые трудности. Надеюсь, кто-нибудь сможет мне помочь.
Мне нужна функция python, которая перебирает множество файлов в разных вложенных папках в папке большего размера, чтобы подсчитать общее количество вхождений данного слова (даже если их несколько в одной строке).
Таким образом, результат, который я должен получить, — это число, но на самом деле я получаю «Никаких результатов». напечатано сотни раз.
Это код, может кто-нибудь сказать мне, что я делаю не так? Спасибо!

 import so
import re

rootdir = "/path/Desktop/folder"
regex = re.compile(r'bwordb')
count = 0

for root, dirs, files in os.walk(rootdir):
    for file in files:
        if regex.findall(file):
            count = count   1
            print(count)
        else: 
            print("No results.")

 

Комментарии:

1. Вам нужно учитывать, что функция findall возвращает список элементов с соответствующим шаблоном. docs.python.org/3/library/re.html#re.findall

Ответ №1:

Вы получаете "No results." снова и снова, потому что печатаете в каждом цикле.

Чтобы получить желаемый результат, сделайте это:

 import os
import re

rootdir = "/path/Desktop/folder"
regex = re.compile(r'bwordb')
count = 0

for root, dirs, files in os.walk(rootdir):
    for file in files:
        if regex.findall(file):
            count = count   1

if count > 0:
    print(count)
else: 
    print("No results.")
 

Без регулярного выражения, допускающего частичные совпадения:

 import os

rootdir = "/path/Desktop/folder"
searched_word = "word"
count = 0

for root, dirs, files in os.walk(rootdir):
    for file in files:
        if searched_word in file:
            count = count   1

if count > 0:
    print(count)
else: 
    print("No results.")
 

Комментарии:

1. Вы ищете слово в имени текстового файла только с помощью этого решения, а не внутри текстового файла. Из того, что я понял из вопроса OP, это не тот способ сделать это

2. @reb не могли бы вы уточнить, нужно word ли указывать имя файла или весь путь?

3. @reb в этом случае я чувствую, что регулярное выражение является излишним и, возможно, вызывает проблему. Добавлено изменение, которое ищет любой файл , содержащий "word" , не требующий быть началом/концом.

Ответ №2:

Вы не читаете текст внутри файла, а на самом деле просто ищете слово в имени файла. Вы можете выполнить печать(файл), чтобы увидеть, что вы ищете.

 import os
import re

rootdir = "/path/Desktop/folder"
regex = re.compile(r'bwordb')
count = 0

for root, dirs, files in os.walk(rootdir):
    for filename in files:
        with open(f'{path}/{filename}','r'):
            for line in f.readlines():
                if regex.findall(line):
                    count  =1
                    print(count)
    
 

Однако это может быть не лучшим способом при работе с большими файлами.

Ответ №3:

Я делаю вывод, что вы пытаетесь рекурсивно найти все текстовые файлы в структуре каталогов, открыть их для чтения, подсчитать совпадения регулярных выражений в каждом файле и подсчитать общее количество совпадений во всех файлах.

В этом случае вы забыли открыть каждый файл по мере его обнаружения, и вы на самом деле не учитываете вхождения в содержимое файла — вы пытаетесь сопоставить регулярное выражение с именем файла. Кроме того, в настоящее время вы увеличиваете только count на единицу, если текущее имя файла содержит по крайней мере одно совпадение. Мне кажется, что вы хотите увеличить count значение на сколько бы случаев ни было обнаружено в содержимом файла.

Вот как я мог бы это написать. Я не проверял это, но я думаю, что это должно сработать:

 import re
from pathlib import Path

pattern = r"bwordb"

def get_occurrences(path):
    return len(re.findall(pattern, path.read_text()))

total = sum(map(get_occurrences, Path("/path/Desktop/folder").rglob("*.txt")))
if total:
    print(f"Total number of occurrences: {total}"))
else:
    print("No occurrences")
 

Комментарии:

1. Большое вам спасибо за потраченное время. Действительно, вы прекрасно поняли, что я должен делать и что мне нужно, еще раз спасибо. Я попробовал ваш скрипт, но функция завершается без каких-либо результатов, ни «Нет вхождений», ни общего количества вхождений, но, честно говоря, я не могу понять, в чем может быть проблема. Кроме того, файлы, к которым я должен применить скрипт, указаны как текстовые/простые и не имеют расширения, поэтому было бы правильно указать их с помощью .rglob («.»)))?

2. На какую утилиту или программное обеспечение указывает text/plain ? Для меня это наводит .txt на мысль о расширении. Если у них действительно нет расширения, вы можете попробовать изменить шаблон "*" глобуса, чтобы захватить все файлы (любое имя файла, любое расширение, даже отсутствующие). Однако имейте в виду, что это также приведет к обнаружению любых других файлов, которые могут находиться в любом месте вашей структуры каталогов.

3. Кроме того, действительно ли нет ошибок/исключений? Если ошибок нет, скрипт должен вывести одно из двух сообщений. Возможно, если у вас много файлов, и каждый файл очень большой, вы просто недостаточно долго ждали завершения сценария.

4. 1. Я на Ubuntu, и тип файла, указанный в информации, таков plain text document (text/plain) . Файл был автоматически сгенерирован сценарием, который я не мог редактировать, поэтому у меня не было выбора. Но в каталоге больше ничего нет , кроме этих файлов, так что я определенно пойду "*" , большое вам спасибо. 2. Ошибок нет, и сценарий на самом деле заканчивается очень рано. Я запускаю его из командной строки Ubuntu, и даже через секунду он заканчивается, и я могу ввести новую команду, поэтому я думаю, что он даже не начинает прокручивать файлы.

5. Возможно ли, что сценарий даже не запустился из if __name__ == "__main__" -за этого ? Я удалил его, попробуй сейчас.

Ответ №4:

Также вы можете попробовать это регулярное выражение, чтобы уловить слово, если оно внутреннее в другом слове

  b(w*wordw*)b