0

请不要笑。我正在尝试编写一个简单的脚本来替换基本 VM 的主机名和 IP。我有一个工作版本,但我正在努力使它更具可读性和简洁性。尝试以下代码时出现语法错误。我试图做出这些列表推导,但由于它们是文件类型,所以这是行不通的。提前致谢。

try:
   old_network = open("/etc/sysconfig/network", "r+")
   new_network = open("/tmp/network", "w+")
   replacement = "HOSTNAME=" + str(sys.argv[1]) + "\n"

   shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak')
   for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line)
   for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line)
   os.rename("/tmp/network","/etc/sysconfig/network")
   print 'Hostname set to', str(sys.argv[1])
except IOError, e:
    print "Error %s" % e
    pass
4

1 回答 1

3

您在这里使用了一些奇怪的语法:

for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line)
for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line)

您需要在此处反转if语句,并将它们放在单独的行中;您必须组合循环,这样您也可以简化if语句:

for line in old_network:
    if not re.match("HOSTNAME", line):
        new_network.write(line) 
    else:
        new_network.write(replacement)

你不能真正循环两次输入文件(你的第二个循环不会做任何事情,因为文件已经被完整读取)。

接下来,您想使用打开的文件对象上下文管理器(使用with)确保它们正确关闭,无论发生什么。您可以从文件模式中删除+,您没有在混合模式下使用文件,并且最好先完成备份副本,然后再打开任何内容进行读取和写入。

这里不需要使用正则表达式;您正在测试是否存在一个简单的简单字符串,会做,'HOSTNAME' in line或者可能line.strip().startswith('HOSTNAME')要确保该行.HOSTNAME

使用该tempfile模块创建一个名称不会冲突的临时文件:

from tempfile import NamedTemporaryFile

shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak')

replacement = "HOSTNAME={}\n".format(sys.argv[1])
new_network = NamedTemporaryFile(mode='w', delete=False)

with open("/etc/sysconfig/network", "r") as old_network, new_network:
    for line in old_network:
        if line.lstrip().startswith('HOSTNAME'):
            line = replacement
        new_network.write(line) 

os.rename(new_network.name, "/etc/sysconfig/network")
print 'Hostname set to {}'.format(sys.argv[1])

fileinput您可以通过使用该模块进一步简化此操作,该模块可让您通过简单的打印来替换文件内容;它支持本地创建备份文件:

import fileinput
import sys

replacement = "HOSTNAME={}\n".format(sys.argv[1])

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'):
    if line.lstrip().startswith('HOSTNAME'):
        line = replacement
    sys.stdout.write(line)

print 'Hostname set to {}'.format(sys.argv[1])

那是 6 行代码(不计算导入)与您的 12 行代码。我们可以通过使用条件表达式将其压缩到仅 4 行,但我不确定这是否会使事情更具可读性:

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'):
    sys.stdout.write(replacement if line.lstrip().startswith('HOSTNAME') else line)
于 2013-05-09T16:40:03.510 回答