заменить и добавить несколько строк, используя findall - PullRequest
0 голосов
/ 01 июля 2018

Я пытаюсь добавить несколько строк в файл (input.txt) и заменить несколько строк в одном файле (input.txt), но мой код вставляет только строки в конец файла. Знаете ли вы, как я могу исправить код, чтобы получить ожидаемый выходной файл, который я хочу?

Мой код:

import re

searchtext1 = """
AB     3.483e-01   2.52e-02 ; 3.46 0.0123
"""
# add these lines after searchtext1
addtext1 = """
CD     2.123e-01   1.31e-02 ; 7.25 0.0145
DE     4.896e-01   7.25e-02 ; 8.25 0.0185
"""
searchtext2 = """
; atom
#atomnumber

#molecule
[weight]
"""
# replace these lines to searchtext2
changetext2 = """
; iron
#48kcal
35 mol
#12 g
"""

with open('input.txt', 'ab+') as infile:
    matches1 = re.findall(r'^(\d+)\.(.*)$', searchtext1, re.MULTILINE)
    infile.write(addtext1)

    matches2 = re.findall(r'^(\d+)\.(.*)$', searchtext2, re.MULTILINE)
    infile.write(changetext2)

input.txt:

[atom]
123
[bonds]
XY     4.212e-01   4.18e-02 ; 8.01 0.0487
AB     3.483e-01   2.52e-02 ; 3.46 0.0123

[molecule]
1 2
3 4
TY     0.412e-01   1.72e-02 ; 0.32 0.0455

; atom
#atomnumber

#molecule
[weight]
calculated value is 5 kcal/mol
end file

ожидаемый выходной файл:

[atom]
123
[bonds]
XY     4.212e-01   4.18e-02 ; 8.01 0.0487
AB     3.483e-01   2.52e-02 ; 3.46 0.0123
CD     2.123e-01   1.31e-02 ; 7.25 0.0145
DE     4.896e-01   7.25e-02 ; 8.25 0.0185

[molecule]
1 2
3 4
TY     0.412e-01   1.72e-02 ; 0.32 0.0455

; iron
#48kcal
35 mol
#12 g
calculated value is 5 kcal/mol
end file

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Как отметил Крис в комментариях, я бы предложил попробовать использовать библиотеку, которая уже может взаимодействовать с форматом - configparser кажется мне очевидным выбором, но могут быть причины, если формат может отличаться из того, что в вашем вопросе.

Кроме того, если вы хотите использовать re, я немного обновил ваш код. Вот твики, которые я сделал:

  • Удалены символы новой строки в начале и конце строк с тройными кавычками, так как они станут частью матча, что может или не может быть тем, что вы хотите. Лично я предпочитаю четко указывать переводы строк при фактической замене.

  • Экранируется [ и ] в тексте поиска, так как они являются специальными символами в re и будут путать его (они указывают класс символов).

  • Используется with для открытия отдельных входных и выходных файлов. Они очищаются при выходе из блока with. Если вы действительно хотите заменить input.txt, я полагаю, вы могли бы потом переместить output.txt поверх.

  • Вы можете использовать re.sub для прямой замены экземпляров, а не для их поиска, поиска индекса в тексте, а затем замены / добавления. В случае добавления текста я только что произвел замену searchtext1 и addtext1. (Я использовал f-строку, но вы также можете сделать "{search}\n{add}".format(search=searchtext, add=addtext1), если хотите.

  • Наконец, мы записываем обновленный текст обратно на диск.

Надеюсь, это поможет!

import re

searchtext1 = """AB     3.483e-01   2.52e-02 ; 3.46 0.0123"""
# add these lines after searchtext1
addtext1 = """CD     2.123e-01   1.31e-02 ; 7.25 0.0145
DE     4.896e-01   7.25e-02 ; 8.25 0.0185"""

searchtext2 = """; atom
#atomnumber

#molecule
\[weight\]"""
# replace these lines to searchtext2
changetext2 = """; iron
#48kcal
35 mol
#12 g"""

with open('input.txt', 'r') as infile, open("output.txt", "w") as outfile:
    intext = infile.read()

    intext = re.sub(searchtext1, f"{searchtext1}\n{addtext1}", intext)
    intext = re.sub(searchtext2, changetext2, intext)

    outfile.write(intext)
0 голосов
/ 01 июля 2018

Вы открыли свой файл в режиме добавления «ab +», который указывает, что все записи будут идти до конца файла. Чтобы изменить части файла так, как вы хотите, вы должны переписать весь файл.

Распространенным шаблоном является создание нового временного файла, запись новых данных, а затем перемещение нового файла поверх старого. Таким образом, перезапись является атомарной, и у вас меньше шансов потерять данные в случае сбоя вашей программы.

...