4

I'm trying to replace a string in a file:

$RELEASE     = '1234';

The whitespace between RELEASE and the = symbol could be either spaces OR tabs. The quotes around the version number could be either single or double.

I currently am assuming spaces and single quotes at the moment just to try to get it working:

sed 's/$RELEASE[[:space:]]*\=[[:space:]]*'\''[0-9]*'\'';/$RELEASE = '\''1234'\'';/g' config.ini > config.ini

So after a lot of work, this works. But only if the string is spaces (as apposed to tabs) and single quotes as apposed to doubles. Here is what I have so far for trying to tackle the tabs...:

sed 's/$RELEASE([[:space:]]|\t)*\=([[:space:]]|\t)*'\''[0-9]*'\'';/$RELEASE = '\''1234'\'';/g' config.ini > config.ini

I've just read that /t isn't supported in most sed regular expressions... Is this true? Is there a [[:tab:]] type replacement? (I did try that)

Any help would be appreciated.

5
  • What are you trying to achieve?
    – drs
    Jul 21, 2014 at 13:31
  • Just write a new one, e.g. sed 's/^$RELEASE.*;$/$RELEASE = "foobar";/' Jul 21, 2014 at 13:32
  • drs, I'm trying to find the $RELEASE string in the file and replace it (this is in an ApacheAnt script) Could be $RELEASE = '1222'; or $RELEASE = "1221";
    – Chris
    Jul 21, 2014 at 13:40
  • Thanks Ulrich. Good suggestion! I've over complicated that for myself somewhat!!!
    – Chris
    Jul 21, 2014 at 13:42
  • 1
    Do not redirect file to itself. In the end you may stay with an empty file. Use sed -i (only for gnu sed) instead or separate temporary file. Also you can use \s instead of [[:space:]] as it also includes \t and all other whitespaces.
    – rush
    Jul 21, 2014 at 14:10

2 Answers 2

2

I don't have any problem with [[:space:]]. Here's a really silly little example showing the mixed-replacement of spaces and tabs:

$ echo -e 'A \t \t B' | sed 's/A[[:space:]]*B/WORKED/'
WORKED

You can also use \s which is often preferable with big sed strings because it's much shorter:

$ echo -e 'A \t \t B' | sed 's/A\s*B/WORKED/'
WORKED

Anyway, I think your actual problem is escaping those troublesome single quotes. I find the easiest way is to break out of the single quote string and have a double-quoted single quote and then (if needed) go back into the single quote line. Bash will automatically concatenate this all up for you.

$ echo 'This is a nice string and this is a single quote:'"'"' Nice?'
This is a nice string and this is a single quote:' Nice?

So all the space we saved with \s is about to get destroyed by this mega-quote situation:

$ echo -e '$RELEASE  \t = '"'"'1234'"'"';' |\
  sed 's/$RELEASE\s*=\s*'"'"'[0-9]*'"'"'\;/REPLACEMENT/'

Of course there is an argument that (because this looks like a PHP script) that you might be able to assume that if the line starts with $RELEASE[\s=]+ you can just replace the whole line. Not always true obviously (the entire app could be one hideous line) but it makes your search and replace more palatable:

sed 's/$RELEASE[\s=]*.*/REPLACEMENT/'

And yes, general sed usage rules apply. Don't echo into a stream-editor (like sed) and redirect back into that file. If it works you could easily knacker the file.

Either use the -i argument (works for sed) or pipe into a application like sponge (which is like a delayed output):

sed -i '...' file
sed '...' file | sponge file
0

You can group the expression and use \1 to point to the group. E.g

sed 's/^\($RELEASE.*=\).*/\1 '"'1234'"'/' config.ini

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .