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.

  • What are you trying to achieve? – drs Jul 21 '14 at 13:31
  • Just write a new one, e.g. sed 's/^$RELEASE.*;$/$RELEASE = "foobar";/' – Ulrich Dangel Jul 21 '14 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 '14 at 13:40
  • Thanks Ulrich. Good suggestion! I've over complicated that for myself somewhat!!! – Chris Jul 21 '14 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 '14 at 14:10

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/'

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/'

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

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.