Я новичок в Python и пытаюсь сделать простое приложение редактора конфигурации.

У меня есть .txt файлы, которые внутри него содержат кучу слов count, таких как:

...
...
max_count=1000
count=123
host_count=000
...
...

В моем случае я хочу изменить только точное совпадение слов с count= в качестве ключа к count=0 и любым числом на этом (после знака =), я хочу заменить его на значение, которое пользователь дал из поля ввода, игнорируя другие значения, такие как max_count=, host_count=, etc. Возможно ли это сделать?

Например:

Когда пользователь вводит 0 в поле ввода, результатом будет count=0

Когда пользователь вводит 1 в поле ввода, результатом будет count=1

Другие xxx_count= или count_xxx= будут игнорироваться

Я попытался сделать это, как показано ниже, но все подсчеты заменены, а не только слова совпадений count=.

files = Finder(self.path, self.name).find()

    for file in files:
        with open(file) as target:
            content = target.read()

            if self.target in content:
                print(content)
                content = content.replace(self.target, self.value)

                with open(file, "w") as target:
                    target.write(content)
            else:
                print('{} not found in {}'.format(self.target, file))

Пожалуйста помоги.

ОБНОВЛЕНИЕ

Вот мой класс Finder (он используется только для поиска файлов).

import os


class Finder:
    result = []

    """
    Create new instance.
    :param {string} path: the directory of the target file.
    :param {string} name: the name of the file.
    """

    def __init__(self, path, name):
        self.path = path
        self.name = name

    # Find files in the given path.
    def find(self):
        directory_exists = os.path.isdir(self.path)

        if not directory_exists:
            return print('Tidak dapat menemukan file {} di folder: {}.'.format(self.name, self.path))

        for root, dirs, files in os.walk(self.path):
            for file in files:
                if self.name in file:
                    self.result.append(os.path.join(root, file))

        return self.result

И это полная версия моего Modifier класса:

from modules.Finder import Finder
from pprint import pprint


class Modifier(Finder):
    """
    Create new instance.

    :param target: target to be modified.
    :param value: value to be used on target.
    """

    def __init__(self, path, name, target, value):
        self.target = target
        self.value = value
        Finder.__init__(self, path, name)

    def modify(self):
        files = Finder(self.path, self.name).find()

        if not files:
            return files

        for file in files:
            with open(file) as target:
                content = target.read()

                if self.target in content:
                    print(content)
                    content = content.replace(self.target, self.value)

                    with open(file, "w") as target:
                        target.write(content)
                else:
                    print('{} not found in {}'.format(self.target, file))

ОБНОВЛЕНИЕ 2

Просто чтобы убедиться, что все понимают, что я хочу сделать. Это мой App.py файл, который контролирует программу.

from pprint import pprint
from modules.Modifier import Modifier

SMSGW = Modifier('D:\\Smsgw', 'SMSGW.ini', 'count=', 'count=0')

settings = SMSGW.modify()
pprint(settings)
1
Tamma 1 Май 2019 в 15:33

3 ответа

Лучший ответ

Используйте регулярное выражение ^count=\d+$ для замены точного соответствия count=somenumber

Принимая во внимание : user_input - ввод, введенный пользователем, а content - данные, считанные из файла.

import re
re.sub(r'^count=\d+$', 'count={}'.format(user_input), content)
3
Kaushal 1 Май 2019 в 13:11

Я вижу, что в большинстве случаев вы используете оператор in для проверки строк. Как здесь:

if self.name in file:

Или здесь

if self.target in content:

Я думаю, что это не то, что вам нужно. Операторы in проверяют, содержится ли строка в других строках, например, 'a' in 'bac' возвращает True. А также count= в max_count= возвращает True. Так что проблема может возникнуть отсюда.

Я думаю, вам нужно проверить на точное равенство, поэтому вы должны изменить эти строки в:

if self.name == file:

Или

if self.target == content:

Теперь, чтобы использовать это решение, вам нужно отделить значение от цели. Используйте метод split.

Например, если content равен "count=123", вы можете сделать:

sepcontent = content.split('=')

Это создаст список sepcontent, который будет ['count', '0']. Вы можете проверить равенство в первом элементе if self.target == sepcontent[0].

И вам определенно нужно повторять построчно при этом. Поэтому не используйте target.read(), который создаст единственную строку из полного файла.

В конце у вас должно получиться что-то вроде:

wfile = 'tempfile.txt'
with open(file) as target:
    with open(wfile, 'w') as wtarget:
        for content in target:
            sepcontent = content.split("=")
            if sepcontent[0] == "count": #or your self.target
                content = content.replace(spline[1], self.value)
            wtarget.write(content)

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

0
Valentino 1 Май 2019 в 13:22

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

Если ваша строка s = 'x_count=1\ncount=0\ncount_xx=0' или

x_count=1
count=0
count_xx=0

Вы можете использовать регулярное выражение, чтобы найти и заменить число после count=

import re
s = 'x_count=1\ncount=0\ncount_xx=0'
## user inputs the number 1, so we replace the current number with 1
new_s = re.sub(r'\ncount=(\d)', r'\ncount=1', s)

Дайте мне знать, если это полезно или нет!

Редактировать:

import re
user_input = 1
for file_name in list_of_file_names:
    with open(file_name) as f:
        new_file_content= re.sub(r'\ncount=(\d)', r'\ncount=%d'(user_input), f.read())

    with open(file_name, "w") as f:
        f.write(new_file_content)
0
SRT HellKitty 1 Май 2019 в 13:53