如何从文件中删除特定行但保持其他行完整?

时间:2012-06-22 01:03:34

标签: python strip

我想学习Python,所以我开始编写我的第一个程序,这是一个电话簿目录。 它可以选择添加姓名和电话号码,删除号码以及搜索号码。 我已经被困在删除部分约2天了,只是无法让它正常工作。我一直在Python IRC和一切,但一直没能弄明白。 基本上,我的程序将数字存储到文件中的列表中。我无法弄清楚如何删除文件中的特定行,但保持文件的其余部分完好无损。有人可以帮帮我吗?

有些人建议,如果我创建一个临时文件,删除该行,然后将原始文件中的剩余行复制到临时文件,将会更容易。然后使用临时文件覆盖原始文件。所以我一直在尝试这个...

if ui == 'remove':  
    coname = raw_input('What company do you want to remove? ') # company name
    f = open('codilist.txt', 'r') # original phone number listing        
    f1 = open('codilist.tmp', 'a') # open a tmp file

    for line in f:  
        if line.strip() != coname.strip():    
            for line in f: 
                f1.write(line)                             
            break         # WILL LATER OVERWRITE THE codilist.txt WITH THE TMP FILE
        else:
            f1.write(line)
    else:
        print 'Error: That company is not listed.'    
    f1.close()
    f.close()
    continue

6 个答案:

答案 0 :(得分:3)

我假设您的文件包含类似< name >< whitespace >< number >在每一行?如果是这种情况,你可以在if语句中使用类似的东西(不包括错误处理!):

name, num = line.strip().split()
if name != coname.strip():
    # write to file



建议:

除非您有某些特定原因要使用自定义格式,否则json的文件格式对于此类任务非常有用。另请注意在这些示例中使用'with'语句,这样可以节省您显式关闭文件的时间。

写信息:

import json

# Somehow build a dict of {coname: num,...}
info = {'companyA': '0123456789', 'companyB': '0987654321'}

with open('codilist.txt', 'w') as f:
    json.dump(info, f, indent=4) # Using indent for prettier files

阅读/修改文件:

import json

with open('codilist.txt', 'r+') as f:

    info = json.load(f)

    # Remove coname
    if coname in info:
        info.pop(coname)
    else:
        print 'No record exists for ' + coname

    # Add 'companyC'
    info['companyC'] = '0112233445'

    # Write back to file
    json.dump(info, f, indent=4)

这些示例需要python2.6或更高版本。如果您使用的是2.5,那么您将需要这些导入:

import simplejson as json
from __future__ import with_statement

希望有所帮助!

答案 1 :(得分:1)

这是一个非常广泛的重写版本:

  • 所有手机数据都包含在电话簿类中;数据保存在内存中(而不是为每次调用保存和重新加载)

  • 它使用csv模块加载和保存数据

  • 将个别行为变成简短的功能或方法(而不是一大块代码)

  • 命令被抽象为函数调度字典(而不是if / then测试的级联)

这应该更容易理解和维护。

import csv

def show_help():
    print('\n'.join([
        "Commands:",
        "    help                   shows this screen",
        "    load [file]            loads the phonebook (file name is optional)",
        "    save [file]            saves the phonebook (file name is optional)",
        "    add {name} {number}    adds an entry to the phonebook",
        "    remove {name}          removes an entry from the phonebook",
        "    search {name}          displays matching entries",
        "    list                   show all entries",
        "    quit                   exits the program"
    ]))

def getparam(val, prompt):
    if val is None:
        return raw_input(prompt).strip()
    else:
        return val

class Phonebook(object):
    def __init__(self, fname):
        self.fname = fname
        self.data = []
        self.load()

    def load(self, fname=None):
        if fname is None:
            fname = self.fname
        try:
            with open(fname, 'rb') as inf:
                self.data = list(csv.reader(inf))
                print("Phonebook loaded")
        except IOError:
            print("Couldn't open '{}'".format(fname))

    def save(self, fname=None):
        if fname is None:
            fname = self.fname
        with open(fname, 'wb') as outf:
            csv.writer(outf).writerows(self.data)
            print("Phonebook saved")

    def add(self, name=None, number=None):
        name   = getparam(name,   'Company name? ')
        number = getparam(number, 'Company number? ')
        self.data.append([name,number])
        print("Company added")

    def remove(self, name=None):
        name = getparam(name, 'Company name? ')
        before = len(self.data)
        self.data = [d for d in self.data if d[0] != name]
        after = len(self.data)
        print("Deleted {} entries".format(before-after))

    def search(self, name=None):
        name = getparam(name, 'Company name? ')
        found = 0
        for c,n in self.data:
            if c.startswith(name):
                found += 1
                print("{:<20} {:<15}".format(c,n))
        print("Found {} entries".format(found))

    def list(self):
        for c,n in self.data:
            print("{:<20} {:<15}".format(c,n))
        print("Listed {} entries".format(len(self.data)))

def main():
    pb = Phonebook('phonebook.csv')
    commands = {
        'help':   show_help,
        'load':   pb.load,
        'save':   pb.save,
        'add':    pb.add,
        'remove': pb.remove,
        'search': pb.search,
        'list':   pb.list
    }
    goodbyes = set(['quit','bye','exit'])

    while True:
        # get user input
        inp = raw_input("#> ").split()

        # if something was typed in
        if inp:
            # first word entered is the command; anything after that is a parameter
            cmd,args = inp[0],inp[1:]

            if cmd in goodbyes:
                # exit the program (can't be delegated to a function)
                print 'Goodbye.' 
                break
            elif cmd in commands:
                # "I know how to do this..."
                try:
                    # call the appropriate function, and pass any parameters
                    commands[cmd](*args)
                except TypeError:
                    print("Wrong number of arguments (type 'help' for commands)")
            else:
                print("I didn't understand that (type 'help' for commands)")

if __name__=="__main__":
    main()

答案 2 :(得分:0)

像这样简单的东西将读取所有f,并写出所有不匹配的行:

for line in f:
    if line.strip() != coname.strip():
        f1.write(line)

答案 3 :(得分:0)

Ned的回答看起来应该有效。如果您还没有尝试过,可以在相关行上方设置python的交互式调试器。然后,您可以打印出line.strip()coname.strip()的值,以验证您是在比较苹果与苹果。

for line in f:
    import pdb
    pdb.set_trace()
    if line.strip() != coname.strip():
        f1.write(line)

Here's a list of pdb commands

答案 4 :(得分:0)

您可能不希望以追加('a')模式打开临时文件:

f1 = open('codilist.tmp', 'a') # open a tmp file

另外,请注意

for line in f:
    ...
    f1.write(line)

会在没有换行符的情况下将所有内容写入文件。

您想要的基本结构是:

for line in myfile:
    if not <line-matches-company>:
        tmpfile.write(line + '\n')   # or print >>tmpfile, line

你必须实现<line-matches-company>(问题中没有足够的信息来知道它应该是什么 - 也许你从数据文件中显示了几行......?)

答案 5 :(得分:0)

我得到了这个......

if ui == 'remove':  
    coname = raw_input('What company do you want to remove? ') # company name
    f = open('codilist.txt')
    tmpfile = open('codilist.tmp', 'w')
    for line in f:
        if coname in line:
            print coname + ' has been removed.'
        else:
           tmpfile.write(line)
    f.close()
    tmpfile.close()
    os.rename('codilist.tmp', 'codilist.txt')
    continue