简体   繁体   English

Python替换文本文件中的行

[英]Python replace line in text file

I am trying to manage a host file with a python script. 我正在尝试使用python脚本管理主机文件。 I am new to python and I am having a hard time with figuring out how to replace a line if I find a match. 我是python的新手,如果找到匹配项,我很难确定如何替换一行。 For example, if the address gets changed in a host file for a website I want the script to find it and change it back. 例如,如果地址在网站的主机文件中被更改,我希望脚本找到它并将其改回。 Thanks for your help. 谢谢你的帮助。

import os
import time

#location to the host file to read and write to
hosts_path=r"C:\Windows\System32\drivers\etc\hosts"
#the address I want for the sites
redirect="0.0.0.0"
#the websites that I will set the address for
website_list=["portal.citidirect.com","www.bcinet.nc","secure.banque-tahiti.pf","www.bancatlan.hn","www.bancentro.com.ni","www.davivienda.com.sv","www.davivienda.cr","cmo.cibc.com","www.bi.com.gt","empresas.banistmo.com","online.belizebank.com","online.westernunion.com","archive.clickatell.com"]

#continuous loop
while True:
    with open(hosts_path,'r+') as file:
        content=file.read()
#for each of the websites in the list above make sure they are in the host file with the correct address
        for website in website_list:
            site=redirect+" "+ website
#here is where I have an issue, if the website is in the host file but with the wrong address I want to write over the line, instead the program is adding it to the end of the file
            if website in content:
                if site in content:
                    pass
                else:
                    file.write(site)
            else:
                file.write("\n"+site)
    time.sleep(300)

    os.system('ipconfig /flushdns')

You need to read the file into a list, then changes the index of the list if it needs to be, then writes the list back to the file. 您需要将文件读取到列表中,然后根据需要更改列表的索引,然后将列表写回到文件中。 What you are doing was just writing to the end of the file. 您正在执行的操作只是写入文件末尾。 You can't change a file directly like that. 您不能像这样直接更改文件。 You need to record the changes in a list then write the list. 您需要将更改记录在列表中,然后编写列表。 I ended up having to re-write a lot of the code. 我最终不得不重新编写很多代码。 Here's the full script. 这是完整的脚本。 I wasn't sure what the os.system('ipconfig /flushdns') was accomplishing, so I removed it. 我不确定os.system('ipconfig /flushdns')在做什么,所以我删除了它。 You can easily add it back where you want. 您可以轻松地将其添加回所需的位置。

#!/usr/bin/env python3.6

import time

hosts_path = r"C:\\Windows\\System32\\drivers\\etc\\hosts"
redirect = "0.0.0.0"
website_list = [
    "portal.citidirect.com",
    "www.bcinet.nc",
    "secure.banque-tahiti.pf",
    "www.bancatlan.hn",
    "www.bancentro.com.ni",
    "www.davivienda.com.sv",
    "www.davivienda.cr",
    "cmo.cibc.com",
    "www.bi.com.gt",
    "empresas.banistmo.com",
    "online.belizebank.com",
    "online.westernunion.com",
    "archive.clickatell.com"]


def substring_in_list(the_list, substring):
    for s in the_list:
        if substring in s:
            return True
    return False


def write_websites():
    with open(hosts_path, 'r') as file:
        content = file.readlines()
    for website in website_list:
        site = "{} {}\n".format(redirect, website)
        if not substring_in_list(content, website):
            content.append(site)
        else:
            for line in content:
                if site in line:
                    pass
                elif website in line:
                    line = site
    with open(hosts_path, "w") as file:
        file.writelines(content)


while True:
    write_websites()
    time.sleep(300)

So, you're going to assign the same IP address to every site that doesn't appear in your websites list? 因此,您要为未出现在网站列表中的每个网站分配相同的IP地址吗?

The following would replace what's inside your outermost while loop: 以下内容将替换最外层的while循环中的内容:

# Read in all the lines from the host file,
# splitting each into hostname, IPaddr and aliases (if any),
# and trimming off leading and trailing whitespace from
# each of these components.
host_lines = [[component.strip() for component in line.split(None, 2)] for line in open(host_path).readlines()]

# Process each of the original lines.  
for line in host_lines:
    # Is the site in our list?
    if line[1] in website_list:
        # Make sure the address is correct ...
        if line[0] != redirect:
            line[0] == redirect

        # We can remove this from the websites list.
        website_list.remove(line[1])

# Whatever sites are left in websites don't appear
# in the hosts file.  Add lines for these to host_lines
host_lines.extend([[redirect, site] for site in website_list])

# Write the host_lines back out to the hosts file:
open(hosts_path, 'w').write("\n".join([" ".join(line) for line in host_lines]))

The rightmost join glues the components of each line back together into a single string. 最右边的join将每行的成分重新粘在一起成为一个字符串。 The join to the left of it glues all of these strings together with newline characters between them, and writes this entire string to the file. join它与他们之间的换行符会将所有这些串在一起,而这整个字符串写入文件到左边。

I have to say, this looks like a rather complicated and even dangerous way to make sure your hosts file stays up-to-date and accurate. 我必须说,这似乎是一种相当复杂甚至危险的方法,以确保您的主机文件保持最新和准确。 Wouldn't it be better to just have a cron job scp a known-good hosts file from a trusted host every five minutes instead? 那岂不是更好地只是有一个cron工作scp已知良好的主机从一个可信主机每隔五分钟,而不是文件?

I ended up mixing some of the responses to create a new file to replace the current host file using functions as shown below. 我最终混合了一些响应,以使用如下所示的函数创建一个新文件来替换当前的主机文件。 In addition to this code I am using pyinstaller to turn it into an exe then I setup that exe to run as a auto-start service. 除了此代码外,我还使用pyinstaller将其转换为exe,然后设置该exe作为自动启动服务运行。

#!/usr/bin/env python3.6

import os
import shutil
import time

temp_file = r"c:\temp\Web\hosts"
temp_directory="c:\temp\Web"
hosts_path = r"C:\Windows\System32\drivers\etc\hosts"
websites = ('''# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#   127.0.0.1       localhost
#   ::1             localhost
0.0.0.0 portal.citidirect.com
0.0.0.0 www.bcinet.nc
0.0.0.0 secure.banque-tahiti.pf
0.0.0.0 www.bancatlan.hn
0.0.0.0 www.bancentro.com.ni
0.0.0.0 www.davivienda.com.sv
0.0.0.0 www.davivienda.cr
0.0.0.0 cmo.cibc.com
0.0.0.0 www.bi.com.gt
0.0.0.0 empresas.banistmo.com
0.0.0.0 online.belizebank.com
0.0.0.0 online.westernunion.com
0.0.0.0 archive.clickatell.com''')


def write_websites():
    with open(temp_file, 'w+') as file:
        file.write(websites)


while True:
    if not os.path.exists(temp_directory):
        os.makedirs(temp_directory)
    try:
        os.remove(temp_file)
    except OSError:
        pass

    write_websites()

    try:
        os.remove(hosts_path)
    except OSError:
        pass

    try:
        shutil.move(temp_file,hosts_path)
    except OSError:
        pass

    os.system('ipconfig /flushdns')
    time.sleep(300)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM