Заменить конкретную строку в файле в Python - PullRequest
0 голосов
/ 02 марта 2019

Для начала, потому что я был сожжен раньше кем-то с отключением питания, этот вопрос не для домашней работы.

В любом случае, у меня есть текстовый файл, который выглядит примерно так:

####
# 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" в 2 строки:

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)

По сути, он откроет файл, прочитает построчно всю строку, содержащую конкретную строку, которую я хочу, а затем просто сохранит ее в памяти.Затем снова откройте файл, прочитайте все и просто замените всю эту строку.Затем откройте файл и запишите файл.

Он делает то, что я хочу, но есть ли способ упростить код?

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

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

Примерно так должно работать:

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.

0 голосов
/ 02 марта 2019

Просто используйте

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...