tags:

views:

2589

answers:

3

I have written a very simple bash script to help me migrate from dev to staging. What it does is it deletes all files in staging, copies the files over from dev to stage.

However, the config.inc.php file needs to have the first instance of "dev" to be changed to "stage", and no other instance changed.

Second, everytime I run it (I run the script from the dev directory), i'd like it to write a log back in the dev directory which will append the date/time stamp that I ran the staging bash script into this log.

Thanks.

A: 

The first part (editing your file) can be done well with the stream editor utility sed:

sed -i -e s/dev/stage/ config.inc.php

This edits the file in-place (-i) with no backup, using expression /dev/stage/ (-e) to replace one expression with another.

Konrad Rudolph
that changes every instance of dev to stage
hayalci
A: 

To change a word in a file:

cat config.inc.php | sed 's:dev::stage' > config.inc.php.new

To append to a log file:

echo $timestamp >> mylogfile.log
friol
Congratulations, you've just won a "useless use of cat" award, http://partmaps.org/era/unix/award.html No offense, cheer up :)
hayalci
Agreed on the 'useless cat' - though somewhere, one of the Unix founding fathers comments that cat as a general purpose data collector has some merits, and is an unexpected side-effect of the various alternative redirection mechanisms.
Jonathan Leffler
+3  A: 

This will change only the first appearance of "dev" to "stage"

sed -i '0,/dev/ s/dev/stage/' config.inc.php

Be aware that it changes "devel" into "stageel". This version behaves just like you want, only a "dev" is searched, not a "devel" (in fact, s/\<dev\>/stage/ as the substitution expression should work, but it does not seem to work as expected? I'll be glad if anyone with more sed-fu can explain. )

sed -i  "/\<dev\>/,/\<dev\>/ s/dev/stage/" config.inc.php

For logging:

date >> /path/to/dev/run.log


Added by Jonathan Leffler

  • Assuming other issues are resolved (see below), the second sed command can still change devel to stagel if the line contains, for example, "move devel code from /some/dev/location to /some/stage/location".
  • Also, the second sed command will map each dev found between the first line containing dev and the second such line. This matters if there's more than one matching line, whereas the original '0,/dev/' (or amended '0,/\<dev\>/') only matches the first line as requested.
  • The reason "s/\<dev\>/stage/" doesn't work is not a sed issue but a shell issue. Use single quotes and you'd be almost OK. With double quotes, the back-slash less-than sequence appears to sed as just less-than.
  • Rule of Thumb: use single quotes around any argument in a shell script containing regular expression material. Unlesss it is saturated with single quotes, replace each single quote in the regular expression with the sequence quote, backslash, quote, quote "'\''". (The first quote terminates the single quote string; the backslash quote is a single quote; the last quote restarts the single quote string.)
  • Note that the '-i' option is a GNU extension to sed; it is a legimate part of the answer since the question is tagged Linux, where GNU sed is used; be aware if you need to move to a platform such as Solaris, AIX, HP-UX.
  • Finally, sed does not support extended regular expressions as standard; you have to explicitly enable them in GNU sed with the '-r' option.

In my estimation, assuming overwrite is desirable, the command should be:

sed -i -r '0,/\<dev\>/s/\<dev\>/stage/' config.inc.php
hayalci
The second sed command can still change devel to stagel if the line contains "move devel code from /some/dev/location to /some/stage/location".
Jonathan Leffler
Also, the second sed command will map each dev found between the first line containing dev and the second such line - which would be less of a problem if the pattern matches were identical.
Jonathan Leffler
As for the reason "s/\<dev\>/stage/" doesn't work, it is not a sed issue but a shell issue. Use single quotes and you'd be nearer to OK; with double quotes, the backslash-lessthan sequence appears to sed as just lessthan.
Jonathan Leffler
Finally, sed does not support extended regular expressions as standard; you have to explicitly enable them in GNU sed with the -r option.
Jonathan Leffler