Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question

1 Answer 1

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.

share|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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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