2017-04-25 145 views
1

我正在努力弄清楚我该如何去从文件中删除一行代码块。下面是代码Python从文件中删除一行代码

#!/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() 

正如你可以看到我用追加用户输入的file.txt的。即(格式:ip:port:name)。文件将包含以下条目时,脚本excuted为./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 

现在我想删除文件中的线(S)。 txt当用户输入以同样的方式给出时。上面的代码运行没有任何反应。如果你能帮助我理解,我是一个初学者,真的很友善。此问题与python multiple user args

+0

你想删除什么?你能解释一下吗?可能会有相同的例子。从代码中不太清楚。 – arunk2

+0

@ArunKumar我试图删除第二个代码窗口中提到的那两个块。当脚本运行参数它应该从file.txt中删除相应的条目。谢谢。 – bindo

回答

1

让我指出你错过的小事。

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. 你打开文件的循环和关闭外内。该文件对象超出了范围。使用with可自动为您处理上下文。

  2. 在循环中打开文件是一个坏主意,因为它会创建如此多的文件描述符,这会消耗大量资源。

  3. 您在编写时从未提及过什么是YY

  4. 您可以在这里删除行与您试图要一次删除多个行,所以d = f.readlines()应该d = f.read()

下面是更新的代码。

#!/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. 
+0

非常感谢。你能否再次检查我的代码,因为当脚本以“./del.py 192.168.0.10:80:somename1”运行时,它不会从文件中删除3行或任何内容。我有行主机地址:192.168.0.10:PORT:80 /模式tcp /绑定192.168.0.10:80 somename1。请注意“/”对应于一个新的行,这个窗口不允许我使用回车键。请帮助拉胡尔,我认为我们非常接近。 – bindo

+0

@bindo使用上面的代码,它会工作。你以前的代码有一些空格和制表符,我将它固定在上面的代码中。它正在工作,我再次检查。 – Rahul

+0

非常感谢rahul,你真的是一个天才。我只是尝试了代码并完美地工作。如果您已指定变量中的所有行,而不是强调复杂的正则表达式模式,那么解决此问题的方式非常出色。我用代码稍微摆弄一下代码来搜索和删除带有制表符的行,到目前为止没有问题。 – bindo

0

有多种方式。我试图创建一个新的文件离开所有的块。您可以删除旧文件并将新文件重命名为旧文件。 以下是相同的工作代码。

#!/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 

希望它有帮助!

+0

非常感谢。如果您不介意,请包括来自getNextBlock的评论吗?我的主要目标是学习,这将非常有帮助。 – bindo

+0

现在更有意义。非常感谢。我会再次测试这个 – bindo