删除Python中的多行

删除Python中的多行,python,Python,我有一个文件如下所示: <VirtualHost *:80> ServerName Url1 DocumentRoot Url1Dir </VirtualHost> <VirtualHost *:80> ServerName Url2 DocumentRoot Url2Dir </VirtualHost> <VirtualHost *:80> ServerName REMOVE </Vi

我有一个文件如下所示:

<VirtualHost *:80>
    ServerName Url1
    DocumentRoot Url1Dir
</VirtualHost>

<VirtualHost *:80>
    ServerName Url2
    DocumentRoot Url2Dir
</VirtualHost>

<VirtualHost *:80>
    ServerName REMOVE
</VirtualHost>

<VirtualHost *:80>
    ServerName Url3
    DocumentRoot Url3Dir
</VirtualHost>

服务器名Url1
文档根Url1Dir
服务器名Url2
文档根Url2Dir
服务器名删除
服务器名Url3
文档根Url3Dir
我想删除这段代码的地方(它不会改变):


服务器名删除
我试图通过使用下面的代码来找到整个代码,但它似乎不起作用

with open("out.txt", "wt") as fout:
        with open("in.txt", "rt") as fin:
            for line in fin:
                fout.write(line.replace("<VirtualHost *:80>\n    ServerName REMOVE\n</VirtualHost>\n", ""))
以open(“out.txt”、“wt”)作为fout的
:
打开(“in.txt”、“rt”)作为fin:
对于fin中的行:
fout.write(line.replace(“\n ServerName REMOVE\n\n”,”))
我曾试图找到解决我问题的办法,但结果却是空手而归,所以我非常感谢你的帮助


在你否决投票之前,我很想听听原因。

最快的方法是将整个文件读入一个字符串,执行替换,然后将该字符串写入所需的文件。例如:

#!/usr/bin/python

with open('in.txt', 'r') as f:
      text = f.read()

      text = text.replace("<VirtualHost *:80>\n    ServerName REMOVE\n</VirtualHost>\n\n", '')

      with open('out.txt', 'w') as f:
            f.write(text)
#/usr/bin/python
以open('in.txt','r')作为f:
text=f.read()
text=text.replace(“\n ServerName REMOVE\n\n”,”)
以open('out.txt','w')作为f:
f、 书写(文本)

这是有限自动机解决方案,可以在以后的开发过程中轻松修改。一开始可能看起来很复杂,但请注意,您可以独立地查看每个状态值的代码。您可以在纸上绘制图形(节点作为圆,箭头作为定向边),以获得所做操作的概述

status = 0      # init -- waiting for the VirtualHost section
lst = []        # lines of the VirtualHost section
with open("in.txt") as fin, open("out.txt", "w") as fout:
    for line in fin:

        #-----------------------------------------------------------
        # Waiting for the VirtualHost section, copying.
        if status == 0: 
            if line.startswith("<VirtualHost"):
                # The section was found. Postpone the output.
                lst = [ line ]  # first line of the section
                status = 1
            else:
                # Copy the line to the output.
                fout.write(line)

        #-----------------------------------------------------------
        # Waiting for the end of the section, collecting.
        elif status == 1:   
            if line.startswith("</VirtualHost"):
                # The end of the section found, and the section
                # should not be ignored. Write it to the output.
                lst.append(line)            # collect the line
                fout.write(''.join(lst))    # write the section
                status = 0  # change the status to "outside the section"
                lst = []    # not neccessary but less error prone for future modifications
            else:
                lst.append(line)    # collect the line
                if 'ServerName REMOVE' in line: # Should this section to be ignored?
                    status = 2      # special status for ignoring this section
                    lst = []        # not neccessary 

        #-----------------------------------------------------------
        # Waiting for the end of the section that should be ignored.
        elif status == 2:   
            if line.startswith("</VirtualHost"):
                # The end of the section found, but the section should be ignored.
                status = 0  # outside the section
                lst = []    # not neccessary
status=0#init——等待VirtualHost部分
lst=[]#虚拟主机部分的行
以open(“in.txt”)作为fin,open(“out.txt”,“w”)作为fout:
对于fin中的行:
#-----------------------------------------------------------
#正在等待VirtualHost部分,正在复制。
如果状态==0:

如果line.startswith(“以上的答案是一种务实的方法,那么它首先是脆弱的,不灵活的。
以下是一些不那么脆弱的东西:

import re

def remove_entry(servername, filename):
    """Parse file , look for entry pattern and return new content

    :param str servername: The server name to look for
    :param str filename: The file path to parse content
    :return: The new file content excluding removed entry
    :rtype: str
    """
    with open(filename) as f:       
        lines = f.readlines()        
        starttag_line = None
        PATTERN_FOUND = False       

        for line, content in enumerate(lines):
            if '<VirtualHost ' in content: 
                starttag_line = line       
            # look for entry
            if re.search(r'ServerName\s+' + servername, content, re.I):
                PATTERN_FOUND = True
            # next vhost end tag and remove vhost entry
            if PATTERN_FOUND and '</VirtualHost>' in content:
                del lines[starttag_line:line + 1]
                return "".join(lines)        


filename = '/tmp/file.conf'

# new file content
print remove_entry('remove', filename)
重新导入
def remove_条目(服务器名、文件名):
“”“解析文件,查找条目模式并返回新内容
:param str servername:要查找的服务器名称
:param str filename:解析内容的文件路径
:return:不包括已删除项的新文件内容
:rtype:str
"""
打开(文件名)为f时:
行=f.读行()
starttag_线=无
找到的模式=错误
对于行,枚举中的内容(行):

如果“你不应该做
fin.read()
或其他什么?fin中的行的
是否像这样工作?如果是这样,您将逐行读取文件,因此替换3行将不起作用…一次读取几行:这看起来像一个XML文件,因此可能您可以使用XML解析器来完成该任务。例如,或者。正如卡尔森所写的,您可能应该将问题更新为expres这就是目标。更好的解决方案可能与您现在尝试的略有不同。您甚至可以使用内置模块xml.etree。ElementTree@pepr是的,但我现在的代码也将用于我将来要做的东西,它不是XML,所以它不受删除XML的限制。我实际上在使用这个脚本tead,因为它还可以删除DocumentRoot行,只需进行一些编辑。谢谢!:)当添加更多的
elif status==x:
时,最好同时添加
else:
,以便在未实现新状态的情况下进行诊断。我的经验是,最好不要对状态值重新编号,只需添加一个新值。有限自动机可能需要一些特殊情况,如意外的文件结尾或因此,我选择可见的状态号,如
555
import re

def remove_entry(servername, filename):
    """Parse file , look for entry pattern and return new content

    :param str servername: The server name to look for
    :param str filename: The file path to parse content
    :return: The new file content excluding removed entry
    :rtype: str
    """
    with open(filename) as f:       
        lines = f.readlines()        
        starttag_line = None
        PATTERN_FOUND = False       

        for line, content in enumerate(lines):
            if '<VirtualHost ' in content: 
                starttag_line = line       
            # look for entry
            if re.search(r'ServerName\s+' + servername, content, re.I):
                PATTERN_FOUND = True
            # next vhost end tag and remove vhost entry
            if PATTERN_FOUND and '</VirtualHost>' in content:
                del lines[starttag_line:line + 1]
                return "".join(lines)        


filename = '/tmp/file.conf'

# new file content
print remove_entry('remove', filename)