3

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?

1 Answer 1

1

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.

5
  • 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, 2011 at 12:08
  • i tried, for example, sed 's/HISTSIZE/SPAM/g' ~/.bashrc | grep ~/.bashrc but didn't see any output.
    – wim
    Oct 17, 2011 at 12:24
  • So sorry - stupid typo (obviously I was thinking about something else...) Correct is: yoursedcmd | diff fname -
    – ktf
    Oct 17, 2011 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, 2011 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, 2011 at 13:07

You must log in to answer this question.

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