Как пойти извлечь отдельные части из текстового файла? - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть текстовый файл следующего формата.(steps.txt)

This is the first line of the file.
here we tell you to make a tea.

step 1

Pour more than enough water for a cup of tea into a regular pot, and bring it to a boil.

step 
2

 This will prevent the steeping water from dropping in temperature as soon as it is poured in.

step 3 


When using tea bags, the measuring has already been done for you - generally it's one tea bag per cup.


Я пытаюсь получить шаги в словаре, например, steps_dic ['step 1'] = 'Налейте больше воды для чашки чая в обычный горшок и принеситеэто до кипения.и так далее.** иногда номер шага # будет в следующей строке ** Я читаю файл и написал обертку для итератора в python для анализа строк в коде, а также для проверки hasnext ().

 def step_check(line,prev):
        if line:
        self.reg1 = re.match(r'^step(\d|\s\d)',line)
        if self.reg1:
            self._reg1 = self.reg1.group()
            # print("in reg1: {} ".format(self._reg1))
    if line and  prev:
        self.only_step = re.match(r'^step$',prev)
        if self.only_step:
            self._only_step = self.only_step.group()
            # print("int only step : {} ".format(self._only_step))
        self.only_digit = re.match(r'\d', line)
        if self.only_digit:
            self._only_digit = self.only_digit.group()
            # print("in only digit: {} ".format(self._only_digit))

    if self._reg1:
        self.step = self._reg1
        # print("Returning.. {} ".format(self.step))
        return self.step
    if self._only_step:
        if self._only_digit:
            # print("Only Step : {} ".format(self._only_step))
            # print ("Only Digit: {} ".format(self._only_digit))
            self.step =self._only_step+" "+self._only_digit
            # print("Returning.. {} ".format(self.step))
            return self.step
    else:
        # print("Returning.. {} ".format(self.step))
        return self.step
 with open(file_name, 'r', encoding='utf-8') as f:
        self.steps_dict = dict()
        self.lines = hn_wrapper(f.readlines())#Wrapper code not including
        self.prev,self.line = None,self.lines.next()
        self.first_line = self.line
        self.prev, self.line = self.line, self.lines.next()
        try:
            while(self.lines.hasnext()):
                self.prev,self.line = self.line,self.lines.next()

                print (self.line)
                self.step_name = self.step_check(self.line,self.prev)
                if self.step_name:
                    self.steps_dict[self.step_name]=''
                    self.prev, self.line = self.line, self.lines.next()
                    while(not self.step_check(self.line,self.prev)):
                        self.steps_dict[self.step_name] = self.steps_dict[self.step_name]+ self.line + "\n"
                        self.prev,self.line = self.line,self.lines.next()

Я могу получить только step_dic ['step 1'] = ...... step_dic ['step 3'] = .......... но шаг 2 пропускается.Мне нужно извлечь для step_dic ['step 2'] также.Я не могу понять, как ведёт буфер для текста.

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

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

Это должно быть в состоянии отрегулировать для достижения вашей цели.В основном принимает регулярное выражение из уравнения.Это также загружает файл только по одной строке за раз (не то, чтобы это имело большое значение в этой ситуации).

Вы можете столкнуться с проблемами, если в нижней части файла есть текст, не связанный с шагами, но это должно бытьможет быть скорректирована с учетом этого сценария.Другой проблемой будет, если у вас есть шаги с этим числом в 100, но если вы можете полагаться на строку, начинающуюся со слова «шаг» (без учета регистра), составляющего шаг, вы можете удалить вспомогательную функцию и правую половинуусловная проверка под итератором строки.

with open('text.txt') as f:

    last_key = False
    key = False
    check_next = False
    step_str = False

    my_dict = dict()

    for line in f:

        if line.strip(' \n').lower() == 'step':
            check_next = True
            step_str = line.strip()

        elif line.lstrip().lower().startswith('step') and not check_next:
            if is_int(line[-2:]) and not is_int(line.strip()):
                if key:
                    my_dict[key] = val
                    last_key = key
                    key = line.strip()

                else:
                    key = line.strip()
                    val = ''

        elif check_next and all(s == '\n' for s in line.strip()):
            continue

        elif is_int(line.strip()) and check_next:
            my_dict[key] = val
            last_key = key
            key = '{} {}'.format(step_str, line.strip())
            check_next = False

        elif key:
            val += line

    if key != last_key:
        my_dict[key] = val

Результат:

{'step 1': '\nPour more than enough water for a cup of tea into a regular pot, and bring it to a boil.\n\n', 'step 2': '\nPour more than enough water for a cup of tea into a regular pot, and bring it to a boil.\n\n\n This will prevent the steeping water from dropping in temperature as soon as it is poured in.\n\n', 'step 3': "\nPour more than enough water for a cup of tea into a regular pot, and bring it to a boil.\n\n\n This will prevent the steeping water from dropping in temperature as soon as it is poured in.\n\n\n\nWhen using tea bags, the measuring has already been done for you - generally it's one tea bag per cup."}
0 голосов
/ 18 февраля 2019

Вы можете прочитать весь файл в память и затем запустить

re.findall(r'^step\s*(\d+)\s*(.*?)\s*(?=^step\s*\d|\Z)', text, re.DOTALL | re.MULTILINE)

См. Демонстрационный пример regex

Подробно

  • ^ - начало строки
  • step - step слово
  • \s* - 0+ пробелов
  • (\d+)- Группа 1: одна или несколько цифр
  • \s* - 0+ пробелов
  • (.*?) - Группа 2: любые 0+ символов, как можно меньше
  • \s* - 0+ пробелов
  • (?=^step\s*\d|\Z) - сразу направо, должно быть
    • ^step\s*\d - начало строки, step, 0+ пробелов и цифра
    • | - или
    • \Z - конец всей строки.

Quick Python demo :

import re
text = "This is the first line of the file.\nhere we tell you to make a tea.\n\nstep 1\n\nPour more than enough water for a cup of tea into a regular pot, and bring it to a boil.\n\nstep \n2\n\nThis will prevent the steeping water from dropping in temperature as soon as it is poured in.\n\nstep 3 \n\n\nWhen using tea bags, the measuring has already been done for you - generally it's one tea bag per cup."
results = re.findall(r'^step\s*(\d+)\s*(.*?)\s*(?=^step\s*\d|\Z)', text, re.DOTALL | re.MULTILINE)
print(dict([("step{}".format(x),y) for x,y in results]))

Вывод:

{'step2': 'This will prevent the steeping water from dropping in temperature as soon as it is poured in.', 'step1': 'Pour more than enough water for a cup of tea into a regular pot, and bring it to a boil.', 'step3': "When using tea bags, the measuring has already been done for you - generally it's one tea bag per cup."}
...