#python #python_3x
У меня есть текстовый файл data.txt:
яблоко
банан
абрикос
яблоко
апельсин
апельсин
мандарин
абрикос
абрикос
абрикос
абрикос
абрикос
Я пытаюсь сделать так, чтобы после обработки файла data.txt функцией set_checkpoints()
на выходе получался файл save.txt:
//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
//А//яблоко//А//
//А//апельсин//А//
//А//апельсин//А//
//А//мандарин//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
Но в результате у меня получается вот что:
//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
яблоко
//А//апельсин//А//
апельсин
//А//мандарин//А//
абрикос
абрикос
абрикос
абрикос
абрикос
Решение:
Нужно сделать так, чтобы функция при нахождении нужного слова из массива, продолжил
поиск данного слова до конца файла, а не прерывался на первом же совпадении и переходил
бы к следующему слову. В итоге у меня получается, что он находит из массива fruits
совпадение со словом из текстового файла, отмечает его чекпойтами и переходит к поиску
следующего слова из массива. Как сделать так, чтобы функция работала корректно?
Вот мой код:
import re
path = 'data.txt' # input data
save = 'save.txt' # output data
def open_read(path): # функция открывает и считывает файл
file = open(path, 'r')
content = file.read()
file.close()
#print(content)
return content
Fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов
n=len(Fruits) # определение размера массива Fruits
def set_checkpoints(content): # функция устанавливает checkpoints
for i in range(n):
find = re.compile(Fruits[i])
res = find.search(content)
#lenght = len(find.findall(content)) # определяет общее количество конкретного
найденного слова
#print (lenght)
#for i in range(lenght):
if res == None: continue # Если не обнаружено слово
else:
k1 = res.start()
k2 = res.end()
content = content[:k1]+"//А//"+content[k1:k2]+"//А//"+content[k2:]
print(content)
return content
###############################################
content = open_read(path) # окрываем файл
content = set_checkpoints(content) # обрабатываем файл функцией set_checkpoints()
file = open(save, 'w') # сохраняем файл
file.write(content)
file.close()
P.S.
Я так понимаю тут дело заключается в методе search(), т.к. метод search() ищет по
всей строке, но возвращает только первое найденное совпадение. Тут похоже нужно использовать
метод findall(), т.к. этот метод возвращает список всех найденных совпадений. Но я
не знаю, как в findall() реализовать установку чекпоинтов. Свойства start() и end()
работают только в методе search().
Помогите, пожалуйста.
Ответы
Ответ 1
Не нужны тут регулярные выражения:
fruits = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин']
with open('input.txt', encoding='utf-8') as f_in:
with open('output.txt', 'w', encoding='utf-8') as f_out:
for line in f_in:
# Для удаления справа пустых символов: ' ', '\n', '\r', и т.п.
line = line.rstrip()
# Если фрукт есть в списке
if line in fruits:
f_out.write('//А//{}//А//\n'.format(line))
Если работать с текстом и через функцию:
FRUITS = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин']
def set_checkpoints(text: str) -> str:
# В одну строку
return '\n'.join(
'//А//{}//А//'.format(line)
for line in text.splitlines() if line in FRUITS
)
# NOTE: тот же код, что выше
# new_lines = []
#
# for line in text.splitlines():
# if line in FRUITS:
# new_lines.append('//А//{}//А//'.format(line))
#
# return '\n'.join(new_lines)
with open('input.txt', encoding='utf-8') as f:
content = f.read()
# Обрабатываем файл функцией set_checkpoints()
content = set_checkpoints(content)
with open('output.txt', 'w', encoding='utf-8') as f:
f.write(content)
Результат (output.txt):
//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
//А//яблоко//А//
//А//апельсин//А//
//А//апельсин//А//
//А//мандарин//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
Ответ 2
Если планируется обрабатывать небольшие файлы (заведомо меньшие половины свободной
оперативной памяти), то можно заменять текст без циклов:
import re
from pathlib import Path
fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов
pref, suff = '//А//', '//А//'
text = Path(r'D:\temp\1.txt').read_text(encoding='utf-8')
pat = r'(\b)({})(\b)'.format('|'.join(fruits))
text = re.sub(pat, r'\1{}\2{}\3'.format(pref, suff), text)
Path(r'D:\temp\result.txt').write_text(text, encoding='utf-8')
# check
print(Path(r'D:\temp\result.txt').read_text(encoding='utf-8'))
результат:
//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
//А//яблоко//А//
//А//апельсин//А//
//А//апельсин//А//
//А//мандарин//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//