Python deleting a block of lines from a file

家住魔仙堡 提交于 2019-12-11 06:14:23

问题


I'm struggling to figure out as to how I should go about deleting a block of lines from a file. Below is the code

#!/usr/bin/python
import argparse
import re
import string

##getting user inputs
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')  
args = p.parse_args()
kkk_list = args.input


def printInFormat(ip, port, name):
    formattedText = '''HOST Address:{ip}:PORT:{port} 
                        mode tcp 
                        bind {ip}:{port} name {name}'''.format(ip=ip, 
                                                                port=port, 
                                                                name=name)
    textWithoutExtraWhitespaces =  '\n'.join([line.strip() for line in formattedText.splitlines()])
    # you can break above thing
    # text = ""
    # for line in formattedText.splitlines():
    #       text += line.strip()
    #       text += "\n" 

    return(formattedText)

#####here im writing writing the user inoput to a file and it works great.
#with open("file.txt", "a") as myfile:
#    for kkk in kkk_list:
#         ip, port, name = re.split(":|,", kkk)
#         myfile.write(printInFormat(ip, port, name))

###### here is where im struggling. 
for kkk in kkk_list:
    ip, port, name = re.split(":|,", kkk)
    tobedel = printInFormat(ip, port, name)  
    f = open("file.txt", "r+")
    d = f.readlines()
    f.seek(0)
    if kkk != "tobedel":
        f.write(YY)
f.truncate()
f.close()

As you can see I'm appending the file.txt with user inputs. i.e (format:ip:port:name). File will contain below entries when the script is excuted as ./script.py 192.168.0.10:80:string 192.168.0.10:80:string

Host Address:192.168.0.10:PORT:80
mode tcp
bind 192.168.0.10:80 abc    
Host Address:10.1.1.10:PORT:443
mode tcp
bind 10.1.1.10:443 xyz

Now I want to delete the line(s) from file.txt when the user input is given the same way. With the above code being run nothing happens. I'm a beginner and really appreiciate if you help me understand. This question is related to python multiple user args


回答1:


Let me point out the little things you are missing.

for kkk in kkk_list:
    ip, port, name = re.split(":|,", kkk)
    tobedel = printInFormat(ip, port, name)  
    f = open("file.txt", "r+")
    d = f.readlines()
    f.seek(0)
    if kkk != "tobedel":
        f.write(YY)
f.truncate()
f.close()
  1. You opened the file inside the loop and closing outside. The file object is out of scope. Use with which handles the context automatically for you.

  2. It is a bad idea to open a file inside a loop, because it will create so many file descriptor which consumes a lot of resources.

  3. You never mentioned what is YY when you are writing.

  4. You can delete lines here as you are trying to delete multiple lines in one go, so d = f.readlines() should be d = f.read()

Below is the updated the code.

#!/usr/bin/python
import argparse
import re
import string

p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')  
args = p.parse_args()
kkk_list = args.input # ['192.168.1.10:80:name1', '172.25.16.2:100:name3']


def getStringInFormat(ip, port, name):
    formattedText = "HOST Address:{ip}:PORT:{port}\n"\
                    "mode tcp\n"\
                    "bind {ip}:{port} name {name}\n\n".format(ip=ip, 
                                                                port=port, 
                                                                name=name)

    return formattedText

# Writing the content in the file
# with open("file.txt", "a") as myfile:
#    for kkk in kkk_list:
#         ip, port, name = re.split(":|,", kkk)
#         myfile.write(getStringInFormat(ip, port, name))



with open("file.txt", "r+") as f:
    fileContent = f.read()

    # below two lines delete old content of file
    f.seek(0)
    f.truncate()

    # get the string you want to delete
    # and update the content
    for kkk in kkk_list:
        ip, port, name = re.split(":|,", kkk)

        # get the string which needs to be deleted from the file
        stringNeedsToBeDeleted = getStringInFormat(ip, port, name)

        # remove this from the file content    
        fileContent = fileContent.replace(stringNeedsToBeDeleted, "")

    # delete the old content and write back with updated one
    # f.truncate(0)
    f.write(fileContent)

# Before running the script file.txt contains 

# HOST Address:192.168.1.10:PORT:80
# mode tcp
# bind 192.168.1.10:80 name name1
#
# HOST Address:172.25.16.2:PORT:100
# mode tcp
# bind 172.25.16.2:100 name name3

# After running file.txt will be empty
# as we have deleted both the entries.



回答2:


There are multiple ways do it. I tried to create a new file leaving all the blocks. You can drop the old file and rename the new file as old file. Following is the working code for same.

 #!/usr/bin/python
 import argparse
 import re
 import string

##getting user inputs
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')  
args = p.parse_args()
kkk_list = args.input # ['192.168.1.10:80:name1', '172.25.16.2:100:name3']



# returns the next block from the available file. Every block contains 3 lines as per definition.
def getNextBlock(lines, blockIndex):
    if len(lines) >= ((blockIndex+1)*3):
        line = lines[blockIndex*3]
        line += lines[blockIndex*3+1]
        line += lines[blockIndex*3+2]
    else:
        line = ''

    return line

# file  - holds reference to existing file of all blocks. For efficiency keep the entire content in memory (lines variable)
file = open("file.txt", "r")
lines = file.readlines()
linesCount = len(lines)

# newFile holds reference to newly created file and it will have the resultant blocks after filtering
newFile = open("file_temp.txt","w")


# loop through all inputs and create a dictionary of all blocks to delete. This is done to have efficiency while removing the blocks with O(n) time

delDict = {}
for kkk in kkk_list:
    ip, port, name = re.split(":|,", kkk)
    tobedel = printInFormat(ip, port, name)
    delDict[tobedel] = 1

for i in range(linesCount / 3):
    block = getNextBlock(lines, i)
    if block in delDict:
        print 'Deleting ... '+block
    else:
        #write into new file
        newFile.write(block)

file.close()
newFile.close()

#You can drop the old file and rename the new file as old file

Hope it helps!



来源:https://stackoverflow.com/questions/43613658/python-deleting-a-block-of-lines-from-a-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!