3

I am trying to modify a configuration file using Python. How can I do the equivalent of multiple sed commands in this format:

sed -ci 's/ServerTokens OS/ServerTokens Prod/' /etc/httpd/conf/httpd.conf

most efficiently in Python? This is what I am doing right now:

with open("httpd.conf", "r+") as file:
    tmp = []
    for i in file:
        if '#ServerName' in i:
            tmp.append(i.replace('#ServerName www.example.com', 'ServerName %s' % server_name , 1))
        elif 'ServerAdmin' in i:
            tmp.append(i.replace('root@localhost', webmaster_email, 1))
        elif 'ServerTokens' in i:
            tmp.append(i.replace('OS', 'Prod', 1))
        elif 'ServerSignature' in i:
            tmp.append(i.replace('On', 'Off', 1))
        elif 'KeepAlive' in i:
            tmp.append(i.replace('Off', 'On', 1))
        elif 'Options' in i:
            tmp.append(i.replace('Indexes FollowSymLinks', 'FollowSymLinks', 1))
        elif 'DirectoryIndex' in i:
            tmp.append(i.replace('index.html index.html.var', 'index.php index.html', 1))
        else:
            tmp.append(i)
    file.seek(0)
    for i in tmp:
        file.write(i)

It's needlessly complex since I could just use subprocess and sed instead. Any suggestions?

8
  • And why don't you use subprocess and sed? Commented Apr 3, 2014 at 11:06
  • 1
    Funny. Are you bound to use python if you can do it alternatively? Commented Apr 3, 2014 at 11:06
  • 1
    Pythons equivilant of sed: docs.python.org/2/library/re.html#re.sub Commented Apr 3, 2014 at 11:13
  • 3
    Use python config parser, i.e. docs.python.org/2/library/configparser.html. Makes things easier! Commented Apr 3, 2014 at 11:57
  • 1
    @PythonNoob: the docs say right there, "Lines beginning with '#' or ';' are ignored and may be used to provide comments." Commented Apr 3, 2014 at 15:43

1 Answer 1

1

You can use regular expressions inside of Python in very similar way you do this in sed. Just use Python regular expressions library. You may be interested in re.sub() method, which does equivalent of sed's s command used in your example.

If you want to do this efficiently, you probably have to run only one substitute command per line, skipping it if it was changed, similar way you do this in your example code. In order to achieve that, you may use re.subn instead of re.sub or re.match combined with groups that were matched.

Here's an example:

import re

server_name = 'blah'
webmaster_email = '[email protected]'

SUBS = ( (r'^#ServerName www.example.com', 'ServerName %s' % server_name),
        (r'^ServerAdmin root@localhost', 'ServerAdmin %s' % webmaster_email),
        (r'KeepAlive On', 'KeepAlive Off')
       )

with open("httpd.conf", "r+") as file:
    tmp=[]
    for i in file:
        for s in SUBS:
            ret=re.subn(s[0], s[1], i)
            if ret[1]>0:
                tmp.append(ret[0])
                break
        else:
            tmp.append(i)
    for i in tmp:
        print i,
Sign up to request clarification or add additional context in comments.

1 Comment

care to share an example with re.sub or resubn? It's confusing me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.