Replace the same string several times with different strings in a file using bash

Go To StackoverFlow.com

0

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

2012-04-04 17:23
by jperelli
Can you clarify what you mean by "other, unknown values"? Do you want to replace all /home/user/XXX directories with /var/django or is it more complicated than that - Andrew Clark 2012-04-04 17:29
I'm not sure regex is the right tool for this. Have you thought of just using a config file of some kind? Put the desired dir names in the config file during installation, then just read them into sys.path.append('/path/from/config/')alan 2012-04-04 17:34
@F.J: I edited the question to clarify this. The delimiters are the single quotes - jperelli 2012-04-04 17:46
@alan: the installation is made only by one bash script. The idea is that I modify (search and replace) this strings in order to configure it to this new location, where installation is made. My question is about search and replace, not about how to config or install. I have my reasons for doing it this way - jperelli 2012-04-04 17:50


0

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.

2012-04-11 22:30
by jperelli


1

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

2012-04-04 18:31
by shellter


0

sed 's@home/user/[^/]*@var/django@' file

is it what you are looking for?

it will replace /home/user/any_user to /var/django

2012-04-04 17:35
by wisent
/home/user could be other value, I edited the question to clarify this. The delimiters are the single quotes - jperelli 2012-04-04 17:45


0

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.

2012-04-04 20:10
by swampf0etus


0

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
2012-04-05 10:54
by swampf0etus
Ads