найти конец строки за другим в текстовом файле в Python

#python #text #replace

#python #текст #заменить

Вопрос:

Проблема

Всем привет,

в текстовом файле мне нужно заменить неизвестную строку на другую,

сначала, чтобы найти его, мне нужно найти строку перед ней ‘name Blur2’, так как существует много строк, начинающихся с ‘xpos’:

  name Blur2
 xpos 12279             # 12279 is the end of line to find and put in a variable
  

Код для получения неизвестной строки:

 #string to find:
keyString = ' name Blur2'
f2 = open("output_file.txt", 'w ') 
with open("input_file.txt", 'r ') as f1:
    lines = f1.readlines()
    for i in range(0, len(lines)):
        line = lines[i]
        if keyString in line:
            nextLine = lines[i   1]       
            print ' nextLine: ',nextLine  #result:  nextLine:   xpos 12279
            number = nextLine.rsplit(' xpos ', 1)[1]
            print ' number: ',number  #result: number:  12279
            #convert string to float:
            newString = '{0}n'.format(int(number)  10)
            print ' newString: ',newString    #result: newString:  12289
            f2.write("".join([nextLine.replace(number, str(newString))]))  #this line isn't working
f1.close()
f2.close()
  

итак, я полностью сменил метод, но последняя строка: f2.write … работает не так, как ожидалось, кто-нибудь знал почему?

еще раз спасибо за вашу помощь 🙂

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

1. 5 последних символов line[-5:]

2. обработайте все строки, скопируйте, если они не содержат строку поиска Blur2 , если содержит Blur2 set boolean, если boolean установлен в следующей строке, замените и сбросьте boolean. Также используйте контекстные менеджеры: with open("last_file.txt", 'r ') as f1:

3. спасибо, метод: строка [-5:] идеально работает с моим кодом: f2.write(«».join([i.replace(i[-10:], newPad) если ключевая строка в i else i для i в f1.readlines()]))

4. к сожалению, для замены мне нужно записать ее перед заменой, и я не знаю как, я пытаюсь получить ее с разделением на самом деле…

5. не начинайте переменную с заглавной буквы, в соответствии с соглашением Python, которые являются именами классов

Ответ №1:

похоже, что регулярное выражение поможет, https://regex101.com /.

Регулярное выражение выполняет поиск строки с языком, который определяет шаблон. Я перечислил наиболее важные из них для изучения самого шаблона, но иногда это лучшая альтернатива, чем собственные манипуляции со строками в python.

Сначала вы описываете шаблон, который вы будете использовать, а затем фактически компилируете шаблон. Для проверки строки я определил ее как необработанную строку, используя r «. Это означает, что мне не нужно экранировать внутри строки (пример: печать будет print(») вместо print(r»).

В этом регулярном выражении есть несколько частей.

s для пробелов (символы, такие как пробел, ‘ ‘)

n или r для перевода строки и возврата каретки [^] определяет, какие символы не следует искать (поэтому [^n r] ищет все, что не содержит перевода строки или возврата каретки), * указывает, что в нем может быть 0 или более указанных символов. $ в строке регулярного выражения учитывает все, что находится до конца строки.

таким образом, шаблон ищет ‘name Blur2’ конкретно с любым количеством пробелов после этого и новой строкой. Круглые скобки позволяют отнести это к группе 1 (объяснено позже). Вторая часть ‘([^ n r] *$)’ захватывает любое количество символов, которые не являются новой строкой или возвратом каретки, вплоть до конца этой строки.

Группы учитывают круглые скобки, поэтому ‘(name blue n)’ — это группа 1, а строка, которую вы хотите заменить ‘([^ n r] *$)’ — это группа 2. проверка.sub должен заменить весь текст группой 1 и новой строкой, поэтому он заменяет первую строку первой строкой и заменяет вторую строку вашей новой строкой

 import re
check = r'(name Blur2s*n)([^nr]*$)'
checkre = re.compile(check, re.MULTILINE)
checkre.sub(g<1> newstring, file)
  

Вам нужно установить re.МНОГОСТРОЧНЫЙ поскольку вы проверяете несколько строк, если ‘n’ не совпадает, вы можете использовать [n r z], который получает один из концов строки, возврата каретки или абсолютного конца строки.

Комментарий rioV8 работает, но вы также можете использовать ‘.{5} $’, который учитывает любые 5 символов до конца строки. Это может быть полезно в re

Должна быть возможность получить старую строку с

 oldstring = checkre.search(filestring).group(1)
  

Я еще не играл с span, но

 stringmatch = checkre.search(filestring)
oldstring = stringmatch.group(2)
newfilestring = filestring[0:stringmatch.span[0]]   stringmatch.group(1)   newstring   filestring[stringmatch.span[1]]:]
  

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

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

1. Большое спасибо, но я не понимаю, когда я записываю строку: 12279? мне нужно записать это, потому что позже я уйду, использую его в математической формуле и запишу в другую строку…

2. я ушел редактировать свой вопрос я думаю, что я не был очень явным, может быть, мне нужно разделить ‘xpos’ в строке после имени Blur2, чтобы получить число?

3. Я могу попытаться отредактировать это в конечном итоге, чтобы ответить на вопрос. Регулярное выражение определенно может найти то, что вам нужно, и оно также может заменить его. Вторая группа вернет строку (я думаю, ‘oldstring=checkre.search(file).group (2)’), но замена строки в файле без повторного поиска потребует некоторого редактирования / исследования. Я понятия не имею, какова скорость сравнения в настоящее время, но она не была бы оптимальной.

4. да, действительно, я не очень понимаю этот метод, у вас есть время, чтобы отредактировать его, я буду очень рад, в любом случае спасибо за ответ!

5. Я немного отредактировал это, но я могу попробовать другой ответ позже на этой неделе. То, что у вас есть сейчас, довольно близко (без использования регулярных выражений), но я не вижу, где вы пишете строки, которые не нужно заменять на новый файл. Я постараюсь потратить некоторое время на то, чтобы поиграть с этим позже на этой неделе.

Ответ №2:

Начальная программа была довольно близка. Я немного отредактировал его, чтобы исправить несколько ошибок.

Изначально вы не писали строки, которые нужно было заменить, я не уверен, зачем вам нужно было объединять вещи. Казалось, что просто замена номера напрямую сработала. Python не допускает изменения i в цикле for, и вам нужно пропустить одну строку, чтобы она не была записана в файл, поэтому я изменил ее на цикл while. В любом случае задавайте любые вопросы, которые у вас есть, но приведенный ниже код, похоже, работает.

 #string to find:
keyString = ' name Blur2'
f2 = open("output_file.txt", 'w ') 
with open("test.txt", 'r ') as f1:
    lines = f1.readlines()
    i=0
    while i <len(lines):
        line = lines[i]
        if keyString in line:
            f2.write(line)
            nextLine = lines[i   1]
            #end of necessary 'i' calls, increment i to avoid reprinting writing the replaced line string
            i =1
            print (' nextLine: ',nextLine  )#result:  nextLine:   xpos 12279
            number = nextLine.rsplit(' xpos ', 1)[1]
            #as was said in a comment, this coula also be number = nextLine[-5:]
            print (' number: ',number  )#result: number:  12279
            #convert string to float:
            newString = '{0}n'.format(int(number)  10)
            print (' newString: ',newString)    #result: newString:  12289
            f2.write(nextLine.replace(number, str(newString)))  #this line isn't working
        else:
            f2.write(line)
        i =1
f1.close()
f2.close()