【问题标题】:Python (or Python+Perl) : set value in a configuration filePython(或 Python+Perl):在配置文件中设置值
【发布时间】:2018-05-08 13:59:08
【问题描述】:

我找不到一个我想要的答案。

我习惯用 bash 编写脚本,但我注意到 bash 在处理大型操作时效率太低,所以我正在用 python 重写我的代码。

但我是 python 的菜鸟!所以我谷歌了很多,但在这里我有一个问题...... 我的 bash 脚本中有很多 sed 操作,我想知道在 python 中重新创建它的方法(这将是重写我所有 sed 操作的起点):

sed -i -e "s/\(log_min_messages = \).*/\1notice/" "/opt/PostgreSQL/9.6/data/postgresql.conf"

用“notice”替换该文件中“log_min_messages”之后的所有内容。

基本上就是打开 postgresql.conf 文件,搜索匹配模式“log_min_messages = *”(其中 * 表示 '=' 之后的内容无关紧要)并将 '*' 替换为字符串 'notice'。

例子:

之前

log_min_messages = something

在 sed 命令之后:

log_min_messages = notice

我想知道我是否必须使用're'?

编辑:一个想法是在 python 脚本中实现 Perl 命令,所以如果有人知道如何在 perl 中执行此操作,无论如何都会是一个很好的答案

【问题讨论】:

  • 也许 Perl 更适合?
  • 考虑过了,不幸的是这个脚本有很多事情要做......不仅仅是“sedding”......顺便说一下我可以通过shell从python调用一些perl命令......在这种情况会是什么? (也编辑问题)
  • 可能有些pythonersbash不熟悉,所以你应该简单解释一下,并举一些例子。
  • 编辑了问题,现在应该更清楚了:)

标签: python regex string bash sed


【解决方案1】:

ConfigParser 可以读/写 ini 配置文件。

我不确定它是否能满足您的要求。

参考:https://docs.python.org/2/library/configparser.html

第一步是从文件中读取配置,然后更改配置值中的值,最后将配置写回文件中。

嗯... sed 更简单.. :)

根据Alex Martelli的Solution提出解决方案

如果我们有这样的 test2.cfg:

key1=abcd
key2=abcd3

然后使用下面的代码:

import ConfigParser


class FakeHeader(object):

    def __init__(self, fp, section='zconfig'):
        self.section = '[%s]\n' % section
        self.fp = fp

    def readline(self):
        if self.section:
            try:
                return self.section
            finally:
                self.section = None
        else:
            return self.fp.readline()


class ZConfigParser(ConfigParser.ConfigParser, object):

    def __init__(self, default_section='zconfig'):
        ConfigParser.ConfigParser.__init__(self)
        self.default_section = default_section

    def read(self, fp):
        new_fp = FakeHeader(open(fp), self.default_section)
        return super(ZConfigParser, self).readfp(new_fp)

    def write(self, fp):
        fp = open(fp, "w")
        for (key, value) in self.items(self.default_section):
            fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
        fp.write("\n")

    def get(self, key):
        return super(ZConfigParser, self).get(self.default_section, key)

    def set(self, key, value):
        super(ZConfigParser, self).set(self.default_section, key, value)

# here you can use it to read/write a configure file without section in somehow graceful method. 

zconfig = ZConfigParser()

# read file
zconfig.read("test2.cfg")

print zconfig.get('key1')

zconfig.set('key1', 'alfasjdlfabalalla')

# then you can check test3.cfg which key1=alfasjdlfabalalla
zconfig.write('test3.cfg')

希望对你有帮助。

【讨论】:

  • 如果只有 postgresql.conf 有节就好了 :( 事实上,没有...可以在开头添加一个节,然后通过一些简单的命令将其删除。 .我会试一试,但我认为它真的只适用于“标准”conf文件......
  • @WyattGillette 先生,没问题,请参考此链接stackoverflow.com/questions/2885190/… 我使用相同的方法读取此类文件。我认为很容易改进这一点来读/写没有节的配置文件。
【解决方案2】:

sed 的转换非常简单,我们必须创建一个临时文件 (outfname) 来写入新文本,然后重命名它。 Python 正则表达式是扩展的(就像 Perl 一样),所以括号不会被转义。

字符串r"..." 上的前导r 是一个原始字符串,这意味着它不会尝试翻译像\1 这样的转义字符。

import re
import os

fname = "/opt/PostgreSQL/9.6/data/postgresql.conf"
outfname = fname + '.new'

with open(fname, 'r') as infile, open(outfname, 'w') as outfile:
    for line in infile:
        line = re.sub(r"(log_min_messages = ).*", r"\1notice", line)
        outfile.write(line)

os.rename(outfname, fname)

但是,您不需要正则表达式。因此,您可以省略 import re 并将 line = re.sub(....) 行替换为:

        if 'log_min_messages = ' in line:
            line = line.split('=')[0] + ' notice\n'

in 运算符测试子字符串是否存在,您也许可以改用line.startswith(),但我不确定您的文件格式。请注意,我们必须在此处添加\n 换行符,默认情况下re 方法(和sed)不会将.* 与换行符匹配。

一般来说,如果你可以使用字符串方法而不是正则表达式来完成这项工作,那么代码会更简单、更高效(尽管在这种情况下你是否会看到不同之处值得怀疑)。

【讨论】:

    猜你喜欢
    • 2011-10-14
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2022-01-13
    • 2018-05-22
    • 1970-01-01
    • 2018-12-12
    相关资源
    最近更新 更多