#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()