views:

150

answers:

6

I'am new to Python 3 and could really use a little help. I have a txt file containing:

InstallPrompt=

DisplayLicense=

FinishMessage=

TargetName=D:\somewhere

FriendlyName=something

I have a python script that in the end, should change just two lines to:

TargetName=D:\new

FriendlyName=Big

Could anyone help me, please? I have tried to search for it, but I didnt find something I could use. The text that should be replaced could have different length.

+2  A: 

A very simple solution for what you're doing:

#!/usr/bin/python
import re
import sys
for line in open(sys.argv[1],'r').readlines():
  line = re.sub(r'TargetName=.+',r'TargetName=D:\\new', line)
  line = re.sub(r'FriendlyName=.+',r'FriendlyName=big', line)
  print line,

You would invoke this from the command line as ./test.py myfile.txt > output.txt

Dan Story
you should compile the regex instead.
ghostdog74
@ghostdog74: nah, regexps are compiled automatically by the `re` module and cached.
nosklo
I thought the only the most recent regex was cached
gnibbler
print is a function in Python3
gnibbler
`open(sys.argv[1],'r').readlines()` could be replace by `open(sys.argv[1])`.
J.F. Sebastian
A: 
import fileinput
for line in fileinput.FileInput("file",inplace=1):
    sline=line.strip().split("=")
    if sline[0].startswith("TargetName"):
        sline[1]="new.txt"
    elif sline[0].startswith("FriendlyName"):
        sline[1]="big"
    line='='.join(sline)    
    print(line)
ghostdog74
print is a function in Python3
gnibbler
A: 

Writing to a temporary file and the renaming is the best way to make sure you won't get a damaged file if something goes wrong

import os
from tempfile import NamedTemporaryFile
fname = "lines.txt"

with open(fname) as fin, NamedTemporaryFile(dir='.', delete=False) as fout:
    for line in fin:
        if line.startswith("TargetName="):
            line = "TargetName=D:\\new\n"
        elif line.startswith("FriendlyName"):
            line = "FriendlyName=Big\n"
        fout.write(line.encode('utf8'))
    os.rename(fout.name, fname)
gnibbler
A: 

subs_names.py script works both Python 2.6+ and Python 3.x:

#!/usr/bin/env python
from __future__ import print_function
import sys, fileinput

# here goes new values
substitions = dict(TargetName=r"D:\new", FriendlyName="Big")

inplace = '-i' in sys.argv # make substitions inplace
if inplace:
   sys.argv.remove('-i')

for line in fileinput.input(inplace=inplace):
    name, sep, value = line.partition("=")
    if name in substitions:
       print(name, sep, substitions[name], sep='')
    else:
       print(line, end='')

Example:

$ python3.1 subs_names.py input.txt
InstallPrompt=

DisplayLicense=

FinishMessage=

TargetName=D:\new

FriendlyName=Big

If you are satisfied with the output then add -i parameter to make changes inplace:

$ python3.1 subs_names.py -i input.txt
J.F. Sebastian
+1  A: 

Is this a config (.ini) file you're trying to parse? The format looks suspiciously similar, except without a header section. You can use configparser, though it may add extra space around the "=" sign (i.e. "TargetName=D:\new" vs. "TargetName = D:\new"), but if those changes don't matter to you, using configparser is way easier and less error-prone than trying to parse it by hand every time.

txt (ini) file:

[section name]

FinishMessage=

TargetName=D:\something

FriendlyName=something

Code:

import sys
from configparser import SafeConfigParser

def main():
    cp = SafeConfigParser()
    cp.optionxform = str # Preserves case sensitivity
    cp.readfp(open(sys.argv[1], 'r'))
    section = 'section name'
    options = {'TargetName': r'D:\new',
               'FriendlyName': 'Big'}
    for option, value in options.items():
        cp.set(section, option, value)
    cp.write(open(sys.argv[1], 'w'))

if __name__ == '__main__':
    main()

txt (ini) file (after):

[section name]

FinishMessage = 

TargetName = D:\new

FriendlyName = Big
Brendan Abel
A: 

Hi,

Thanks to all for the many examples. It works great