I often want to automate this sort of task in a shell script:

if the line:

SOMEKEY=SOMEVALUE

exists in a file, then change it to

SOMEKEY=SOMEOTHERVALUE

otherwise, append the line SOMEKEY=SOMEOTHERVALUE in the file.

How could I go about this? I think I could do it using a combination of grep and sed, but I'm sure it's a common enough task that someone has already worked out an elegant solution.

By the way, when replacing I would normally do something like this

sed -i 's/old/new/g' fname

But it means I have to be very careful when composing my regular expressions, so as not to make a mistake. Is there an easy way to "preview" what changes which would occur from my call to sed without actually stomping on the file?

link|improve this question

feedback

1 Answer

up vote 1 down vote accepted

I'd use awk for this task:

   awk -F'=' -v "keyname=$SOMEKEY" -v "value=$SOMEOTHERVALUE" '
            $1 == keyname {
                    if ($2 != value) $2 = "\"" value "\""
                    key_found = 1
            }

            { print $1 "=" $2 }

            END { if (!key_found) print keyname "=\"" value "\"" }
   ' fname

assuming

 SOMEKEY=key1
 SOMEOTHERVALUE="John Doe is dead!"

and given this input:

 key1="John Doe is geat!
 key2="Who's John Wayne?"

One gets:

 key1="John Doe is dead!"
 key2="Who's John Wayne?"

Or if no key1 line is present, key1="John Doe is dead!" will be appended at the end.

Note: On Solaris or other UNIX derivates that still ship an old version of awk(1), nawk(1) should be used instead.

link|improve this answer
Missed that last question: If you just want to preview your changes, omit the option -i and code: yoursedcommand |grep fname - That will compare the outcome of your command with the original file fname – ktf Oct 17 '11 at 12:08
i tried, for example, sed 's/HISTSIZE/SPAM/g' ~/.bashrc | grep ~/.bashrc but didn't see any output. – wim Oct 17 '11 at 12:24
So sorry - stupid typo (obviously I was thinking about something else...) Correct is: yoursedcmd | diff fname - – ktf Oct 17 '11 at 12:37
yes i thought you might have meant diff, but when i tried that i get diff: missing operand after /home/wim/.bashrc'` – wim Oct 17 '11 at 12:40
Don't forget the second argument to diff: it's only a single minus sign (-) which indicates that the 2nd file for comparison shall be read from stdin – ktf Oct 17 '11 at 13:07
show 1 more comment
feedback

Your Answer

 
or
required, but never shown

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