Для начала, поскольку меня уже обжигал кто-то с энергетическим трипом, этот вопрос не для домашнего задания.
Во всяком случае, у меня есть текстовый файл, который выглядит примерно так:
####
# File section 1
####
1.0 abc Description1
6.5 def Description2
1.0 2.0 3.0 ghi Description3
11 jkl Description
####
# File section 2
####
1.0 abc Description1
12.5 def Description2
1.0 2.0 3.0 ghi Description3
11 jkl Description
#### End file
Я хотел бы заменить строку «1.0» в двух строках:
1.0 abc Description1
Однако НЕ строка «1.0» в строках:
1.0 2.0 3.0 ghi Description3
Текущий код, который я использую:
with open('sample_file.txt','r') as file:
filedata = file.read()
filedata = filedata.replace('1.0','2.0')
with open('sample_file.txt','w') as file:
file.write(filedata)
Однако в результате все вхождения «1.0» заменяются. Затем я должен вернуться в файл и исправить ошибку. Результирующий файл, который я хотел бы получить:
####
# File section 1
####
2.0 abc Description1
6.5 def Description2
1.0 2.0 3.0 ghi Description3
11 jkl Description
####
# File section 2
####
2.0 abc Description1
12.5 def Description2
1.0 2.0 3.0 ghi Description3
11 jkl Description
#### End file
Как я могу это получить? Я не смог найти пример решения проблемы такого типа. Спасибо за вашу помощь.
Обновлено: Моя вина в том, что я не уточняю, но строка, которую я хочу заменить, не всегда имеет «1.0» и не всегда имеет длину 3 символа. Например, это может быть «-12,3». Я хотел бы сделать код как можно более универсальным.
Я также пытался использовать rsplit, чтобы изолировать первую строку, используя пробел в качестве разделителя, но, похоже, это не работает для записи файлов.
========================
РЕДАКТИРОВАТЬ2: я нашел способ сделать это, хотя это кажется довольно обходным методом:
with open('sample_file.txt','r') as file:
filedata = file.readlines()
for line in filedata:
if 'abc' in line:
oriline = line
newline = line.replace(str(spk),str(newspk))
with open('sample_file.txt','r') as file:
filedata = file.read()
filedata = filedata.replace(str(oriline),str(newline))
with open('sample_file.txt','w') as file:
file.write(filedata)
По сути, он открывает файл, считывает строку за строкой всю строку, содержащую конкретную строку, которую я хочу, а затем просто сохраняет ее в памяти. Затем снова откройте файл, прочитайте все и просто замените всю эту строку. Затем откройте файл и запишите файл.
Он делает то, что я хочу, но есть ли способ упростить код?
Я хотел бы только заменить строку «1.0» для строк только на «abc» в них, поскольку «abc» — это переменная в коде, который я использую.
Что касается EDIT2: нет причин читать файл дважды. Вы можете изменить элементы filedata на месте, а затем использовать file.writelines на filedata. Кроме того, есть только один oriline, поэтому, если «abc» встречается дважды в одном и том же файле (как в вашем примере), это не сработает. Кроме того, вы выполните замену, если «abc» встречается в строке в любом месте (включая описание), и замените все вхождения spk на newspk (какими бы они ни были), а не только в первом токене. Вы также заявляете, что заменяемая строка не является фиксированной строкой, которую ваш подход не обрабатывает.
Что не так с любым из двух предложенных мной подходов? Они должны соответствовать требованиям, которые вы указали. Если они не подходят, объясните, почему.






Просто используйте
with open('sample_file.txt','r') as file:
filedata = file.read()
filedata = filedata.replace('1.0 abc','2.0 abc')
with open('sample_file.txt','w') as file:
file.write(filedata)
Вместо приведенного выше ярлыка вы можете попробовать более общий случай, сначала определив пустой список:
li = []
а затем используйте приведенный ниже код (учитывая, что строка abc фиксирована, как в приведенном выше случае):
with open('sample_file.txt','r') as file:
for line in file:
i = line.find('abc',1)
if i >= 0:
lineval = line.replace('1.0','2.0')
li.append(lineval)
else:
lineval = line
li.append(lineval)
j = 0
with open('sample_file.txt','w') as file:
while j < len(li):
file.write(li[j])
j += 1
Моя вина в том, что я не уточнил, но строка, которую я хочу заменить, не всегда имеет «1.0» и не всегда имеет длину 3 символа. Например, это может быть «-12,3». Я хотел бы сделать код как можно более универсальным.
Этого может быть достаточно для случая OP, но имейте в виду, что второй пример кода заменит все вхождения «1.0», если в строке появится «abc» в любом месте.
@jamesdlin, конечно, я сделал это намеренно в зависимости от ключевого слова в его образце. Спасибо, в любом случае.
Я попробовал свой собственный метод (EDIT 2), вдохновленный вами, ребята, и, похоже, он работает. Можете ли вы, ребята, предложить некоторую критику того, как я могу улучшить код?
Как я упоминал в комментарии, вы можете использовать регулярные выражения для соответствия шаблону, который вы ищете. Вы можете указать группы в шаблоне (используя (...) или (?P<имя...)), чтобы идентифицировать части шаблона и специально заменить или повторно использовать эти части.
Что-то вроде этого должно работать:
import re
pattern = (r'^' # The beginning of a line.
# Match something that looks like a number:
r'-?' # 1. Optional: a negative sign.
r'\d+' # 2. One or more digits.
r'([.]\d+)?' # 3. Optional: a decimal point followed by one
# or more digits.
# The rest of the line:
r'(?P<rest>'
r'\s+' # 1. One or more spaces.
r'abc' # 2. "abc"
r'\s+' # 3. One or more spaces.
r'.*' # 4. Everything remaining.
r')'
r'$') # The end of a line.
# Replace the above pattern with "2.0" followed by whatever we identified
# as "the rest of the line".
replacement = '2.0\g<rest>'
with open('sample_file.txt','r') as file:
filedata = file.read()
# re.MULTILINE is needed to treat lines separately.
filedata = re.sub(pattern, replacement, filedata, flags=re.MULTILINE)
with open('sample_file.txt','w') as file:
file.write(filedata)
Другой (непроверенный) подход, который не использует регулярные выражения:
with open('sample_file.txt','r') as file:
lines = file.readlines()
with open('sample_file.txt','w') as file:
for line in lines:
tokens = line.split(maxsplit=2)
try:
if float(tokens[0]) and tokens[1] == 'abc':
tokens[0] = '2.0'
except (IndexError, ValueError):
pass
else:
line = ' '.join(tokens)
file.write(line)
Обратите внимание, что это не совсем то же самое, что подход регулярных выражений (RE) (заметные отличия заключаются в том, что он будет принимать любое число с плавающей запятой в качестве первого токена (например, 1e-10) и что он не будет сохранять пробелы после выполнения замены ), но может быть немного проще понять, если вы не знакомы с RE.
Используйте регулярные выражения, чтобы найти нужный шаблон строки и выполнить замену части этого шаблона. Нам трудно дать вам более конкретный ответ, не зная точно, каковы критерии того, что вы хотите заменить (т. е. хотите ли вы заменить «1.0» только для записей с пометкой «abc»? хотите ли вы заменить «1.0 " только если в той же строке нет других чисел?)