How can I automate modifying key/value pairs in a shell script?
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.
Related videos on Youtube
wim
Hi from Chicago! Python dev with interest in mathematics, music, robotics and computer vision. I hope my Q&A have been helpful for you. If one of my answers has saved your butt today and you would like a way to say thank you, then feel free to buy me a coffee! :-D [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo *Click*
Updated on September 18, 2022Comments
-
wim over 1 year
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
andsed
, 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? -
ktf over 12 yearsMissed 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 filefname
-
wim over 12 yearsi tried, for example,
sed 's/HISTSIZE/SPAM/g' ~/.bashrc | grep ~/.bashrc
but didn't see any output. -
ktf over 12 yearsSo sorry - stupid typo (obviously I was thinking about something else...) Correct is: yoursedcmd
| diff fname -
-
wim over 12 yearsyes i thought you might have meant
diff
, but when i tried that i getdiff: missing operand after
/home/wim/.bashrc'` -
ktf over 12 yearsDon'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