Поиск точной строки, сопоставьте ее. Если нет соответствующей записи, добавьте параметр также, если частичное соответствие изменяет файл Python

Вы создаете регулярное выражение, передавая строку конструктору RegExp.

Вам нужно избежать \, чтобы ваш строковый литерал мог выразить его как данные, прежде чем преобразовать его в обычный выражение.

1
задан Abhimanyu 17 January 2019 в 04:22
поделиться

2 ответа

re.sub() принимает 3 параметра, но здесь проблема не в этом. Фактически вы не замените текст, который пытаетесь заменить, простой записью в файл, не пытаясь сначала найти смещение, в которое вы хотите записать, с помощью функции seek(). Это проблема для вас, потому что ваша замещающая строка длиннее, чем оригинал, и вы, вероятно, в конечном итоге будете записывать данные, которые вы не собирались. Другая проблема заключается в том, что вы решили открыть файл для добавления, которое в некоторых системах добавляется ТОЛЬКО в конец файла, что, я уверен, не является вашим намерением.

Все, что вам действительно нужно сделать, это открыть файл и скопировать данные в переменную. Затем попытайтесь найти строку и заменить ее. Наконец, запишите все это обратно в файл.

def write_over():
    file_name = '/etc/sysctl.conf'
    new_string = 'net.ipv4.ipfrag_low_thresh = 15728640'

    fh = open(file_name, 'r+')
    data = fh.read()

    result = re.search(r'net\.ipv4\.ipfrag_low_thresh\s?=?\s?[0-9]*', data) # check this regex, it may not be exactly what you need
    if result:
        if result.group(0) == new_string:  # if the string is exact match, do nothing
            fh.close()
            return
        data = data.replace(result.group(0), new_string + '\n') # else replace with new string
        fh.truncate(0) # this will clear the contents of the file
        fh.seek(0)
        fh.write(data) # write the new data in its entirety to the file
        fh.close()
    else:
        fh.write('\n' + new_string) # if the line was not in the file at all
        fh.close()
0
ответ дан typedef struct James 17 January 2019 в 04:22
поделиться

Вот другой подход, использующий типы данных Python вместо простого строкового регулярного выражения (слишком легко испортить регулярное выражение и разрушить структуру файла).

Работа с поддельным примером файла:

# hash comment
 ; colon comment

one = 1
net.ipv4.ipfrag_low_thresh = 1234
another = ok

код:

#!/usr/bin/env python

setting_map = {
    'net.ipv4.ipfrag_low_thresh': 15728640,
    'net.ipv4.ipfrag_high_thresh': 16777216,
}
found = {setting: False for setting in setting_map}
to_write = []

def good_setting(setting):
    return '{} = {}'.format(setting, setting_map[setting])

with open('sysctl.conf') as f:
    for line in f:
        line = line.rstrip()  # remove newlines

        try:
            setting = line.split('=')[0].strip()  # remove spaces if present
            value = int(line.split('=')[-1].strip())
        except Exception as e:
            # you probably don't want to print, but i put it here for demonstration
            print('could not parse line "{}"; exception: {}'.format(line, repr(e)))
            # keep it as-is
            to_write.append(line)
            continue

        if setting in setting_map:
            found[setting] = True
            if value != setting_map[setting]:
                print('FOUND "{}" with value "{}"; overwriting with "{}"'.format(
                    setting, value, setting_map[setting]
                ))
                to_write.append(good_setting(setting))
                continue

        to_write.append(line)

# opening as 'w' will wipe the file, but we're re-writing every line
# or you can write to a different file if you'd like
with open('sysctl.conf', 'w') as f:
    f.write('\n'.join(to_write))
    f.write('\n')
    for setting in setting_map:
        if not found[setting]:
            print('ADDING "{}"'.format(good_setting(setting)))
            f.write('{}\n'.format(good_setting(setting)))

вывод:

could not parse line "# hash comment"; exception: ValueError("invalid literal for int() with base 10: '# hash comment'")
could not parse line " ; colon comment"; exception: ValueError("invalid literal for int() with base 10: '; colon comment'")
could not parse line ""; exception: ValueError("invalid literal for int() with base 10: ''")
FOUND "net.ipv4.ipfrag_low_thresh" with value "1234"; overwriting with "15728640"
could not parse line "another = ok"; exception: ValueError("invalid literal for int() with base 10: 'ok'")
ADDING "net.ipv4.ipfrag_high_thresh = 16777216"

файл после:

# hash comment
 ; colon comment

one = 1
net.ipv4.ipfrag_low_thresh = 15728640
another = ok
net.ipv4.ipfrag_high_thresh = 16777216
0
ответ дан DeeBee 17 January 2019 в 04:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: