edit text file using Python

前端 未结 6 1291
忘了有多久
忘了有多久 2020-12-14 04:55

I need to update a text file whenever my IP address changes, and then run a few commands from the shell afterwards.

  1. Create variable LASTKNOWN = \"212.171.13

相关标签:
6条回答
  • 2020-12-14 05:29

    fileinput module has very ugly API, I find beautiful module for this task - in_place, example for Python 3:

    import in_place
    
    with in_place.InPlace('data.txt') as file:
        for line in file:
            line = line.replace('test', 'testZ')
            file.write(line)
    

    main difference from fileinput:

    • Instead of hijacking sys.stdout, a new filehandle is returned for writing.
    • The filehandle supports all of the standard I/O methods, not just readline().

    for example - fileinput can line by line editing only, in_pace allow read whole file to memory (if it not big) and modify it.

    0 讨论(0)
  • 2020-12-14 05:31

    Another way to simply edit files in place is to use the fileinput module:

    import fileinput, sys
    for line in fileinput.input(["test.txt"], inplace=True):
        line = line.replace("car", "truck")
        # sys.stdout is redirected to the file
        sys.stdout.write(line)
    
    0 讨论(0)
  • 2020-12-14 05:31

    After checking the comments and the bit of code that you put on pastebin, here is a working solution. To begin with, the file /tmp/iiiipf.conf contains:

    Simply a test file 175.48.204.168
    
    And two times 175.48.204.168 on this line 175.48.204.168
    
    Done.
    

    After running the code, the file /tmp/iiiipf.conf contains:

    Simply a test file 10.73.144.112
    
    And two times 10.73.144.112 on this line 10.73.144.112
    
    Done.
    

    And here is the tested working code with my stuff merged into your pastebin code:

    import socket
    import fileinput
    import subprocess
    import string
    import re
    
    CURRENT = socket.getaddrinfo(socket.gethostname(), None)[0][4][0]
    LASTKNOWN = '175.48.204.168'
    
    if CURRENT == LASTKNOWN:
        print 'Nevermind.'
        subprocess.sys.exit()
    
    else:
    
        cf = open("/tmp/iiiipf.conf", "r")
        lns = cf.readlines()
        # close it so that we can open for writing later
        cf.close()
    
        # assumes LASTKNOWN and CURRENT are strings with dotted notation IP addresses
        lns = "".join(lns)
        lns = re.sub(LASTKNOWN, CURRENT, lns)  # This replaces all occurences of LASTKNOWN with CURRENT
    
        cf = open("/tmp/iiiipf.conf", "w")
        cf.write(lns)
        cf.close()
    

    This bit of code will do what you need even if the IP address is used several times within the configuration file. It will also change it in comment lines.

    This method does not require copying to /tmp and uses one less subprocess call when restarting the firewall and NAT.

    0 讨论(0)
  • 2020-12-14 05:34

    You're trying to "atomically" update the contents of a file, and there have been many delightful flame wars on the subject. But the general pattern is:

    1) Write the new file to a temp file, and make sure you flush and close.

    2) Use your operating system's facilities to atomically rename the temp file to the old file.

    Now, you simply can't atomically rename a file in Windows, but it sounds like you're on a unix-like system anyway. You atomically rename using os.rename().

    0 讨论(0)
  • 2020-12-14 05:35

    Probably the simplest way would be to open a file using f=open(filename, mode). Then, read all the lines using f.readlines() (this will return a list of strings representing the lines of the program).

    You can then search these strings to find the address and replace it with the new one (using standard string replacing, regular expressions, or whatever you want).

    At the end, you can write the lines back to the file using f.writelines(lines), which conveniently takes back a list of lines.

    NOTE: This is not an efficient way to do this, it's just the easiest. Please

    Example code:

    f = open(filename, "r")
    lines = f.readlines()
    
    # Assume that change_ip is a function that takes a string and returns a new one with the ip changed): example below
    ret_lines = [change_ip(lines) for line in lines]
    new_file = open(new_filename, "w")
    new_file.writelines(lines)
    
    def change_ip(str):
       ''' Gets a string, returns a new string where the ip is changed '''
       # Add implementation, something like: return str.replace(old_ip, new_ip) or something similair.
    
    0 讨论(0)
  • 2020-12-14 05:38

    Replace LASTKNOWN by CURRENT in /etc/ipf.conf

    Replace all at once

    filename = "/etc/ipf.conf"
    text = open(filename).read()
    open(filename, "w").write(text.replace(LASTKNOWN, CURRENT))
    

    Replace line by line

    from __future__ import with_statement
    from contextlib import nested
    
    in_filename, outfilename = "/etc/ipf.conf", "/tmp/ipf.conf"
    with nested(open(in_filename), open(outfilename, "w")) as in_, out:
         for line in in_:
             out.write(line.replace(LASTKNOWN, CURRENT))
    os.rename(outfilename, in_filename)
    

    Note: "/tmp/ipf.conf" should be replaced by tempfile.NamedTemporaryFile() or similar
    Note: the code is not tested.

    0 讨论(0)
提交回复
热议问题