I have a file with this content
import os
import sys
sys.path.append('/home/user/dj/project/')
sys.path.append('/home/user/dj/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proj.settings")
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
/home/user/dj/proj/
and /home/user/dj/
could be other, unknown values.
I have a bash script to do an installation, and in there I want to execute something to change those lines to this
import os
import sys
sys.path.append('/var/django/proj/')
sys.path.append('/var/django/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proj.settings")
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
I tried with sed
but I had troubles with greediness in regex.
I tried with perl -pi -e s/str1/str2/
but I had troubles because perl repaces all occurences.
EDIT: To clarify, I want to replace only the values inside the single quotes. i.e:
sys.path.append('foo')
with sys.path.append('what I want')
and
sys.path.append('bar')
with sys.path.append('the second thing I want')
and bar
could be different or equal to foo
sys.path.append('/path/from/config/')
alan 2012-04-04 17:34
I finally used this
sed -i "1,/sys.path.append/ {/sys.path.append/i sys.path.append('$HOMEDIR/')\nsys.path.append('/home/$SYS_USER/')
}" $HOMEDIR/wsgi.py
with that carriage return before the }
is the only thing that worked for me.
As a basis for your solution:
replStr="/var/django"
echo "sys.path.append('/home/user/dj/project/')" \
| sed "s@sys.path.append('[^'][^']*[']@sys.path.append('${replStr}'@"
output
sys.path.append('/var/django')
The trick to getting a non-greedy solution, is to say "[^']" (any char not a sngl-quote). Adding the second "[^']*" (and the star), make the whole setting say, "at least 1 char that is not a single-quote". Then you add a single-quote (I use the char-class container to make it more visible, it may not be needed).
When a search target is known, I prefer just to match it, and then type it out again in my replacment string, rather than try to capture the value inside of ()s and reference with \1. again, just that it makes what is happening a little more obvious to a maintenance coder.
I hope this helps
sed 's@home/user/[^/]*@var/django@' file
is it what you are looking for?
it will replace /home/user/any_user to /var/django
I ran this on the bash command line against a carbon copy of your code (filename
) and it worked a treat;
sed s/sys\.path\.append\(\'.*\'\)/sys\.path\.append\(\'\\/var\\/django\\/proj\\/\'\)/ filename
There's a lot of escaping but works a treat if you're wanting to affect all sys.path.append() calls in your programs. Obviously, it's easy to tweak to work with other function/method calls.
If you want a bash script that you can run against any program to change the string passed into any given function then you could use this;
#!/bin/bash
# Usage: replacer.bash funcname repstring inputfile
# funcname - function/method to affect
# repstring - replacement string that you want passed into the function/method
# inputfile - program/script to process
function main
{
fun=$1
shift
text=$1
shift
sed "s@\\($fun\\)(\'.*\')@\\1\(\'$text\'\)@" $1
}
main $*
Example;
replacer.bash sys.path.append /var/django/proj/ myprog > myprog.new
/home/user/XXX
directories with/var/django
or is it more complicated than that - Andrew Clark 2012-04-04 17:29