I often have to modify files such as sysctl.conf
, and I'm familiar with using sed to replace existing values.
Is there a way to append the new key/value pair to the file if sed wasn't able to replace it?
For instance, using this example: modify config file using bash script
sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE
How could I add the $TARGET_KEY = $REPLACEMENT_VALUE
new line to $CONFIG_FILE
using the same sed expression with slight changes?
And on a related topic, how can I force creation of $CONFIG_FILE
if it didn't exist?
You can't easily do it all in a single sed
call. It's probably simplest to make it two steps:
if grep -q "$TARGET_KEY *= " $CONFIG_FILE; then
sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE
else
echo "$TARGET_KEY = $REPLACEMENT_VALUE" >>$CONFIG_FILE
fi
There are a few things you should probably do to make the above more robust, however:
Your regular expression is not anchored, which means that trying to set 'PORT' will also find/change 'SUPPORT', etc.
It won't match if the config file might have tabs as well as spaces
It fails if the replacement value has slashes in it.
You should always quote parameter expansions like $CONFIG_FILE
, in case the file path contains spaces or shell metacharacters.
It's safe in this instance, but potentially confusing to use single backslashes in a double-quoted string when you want a literal backslash. The shell leaves them alone when it doesn't recognize what comes after it as a special sequence, but it would be clearer if you doubled them.
What does -c
do on your version of sed? Neither my Linux nor Mac versions support such an option.
So I would do it this way (the ^I
's represent literal tab characters, and the ^A
's literal control-A characters, entered by for example typing control-V first on the command line):
if grep -q "^[ ^I]*$TARGET_KEY[ ^I]*=" "$CONFIG_FILE"; then
sed -i -e "s^A^\\([ ^I]*$TARGET_KEY[ ^I]*=[ ^I]*\\).*$^A\\1$REPLACEMENT_VALUE^A" "$CONFIG_FILE"
else
echo "$TARGET_KEY = $REPLACEMENT_VALUE" >> "$CONFIG_FILE"
fi
Use below pseudo code:
if (grep -q key); then
sed...
else
echo key=value >> $CONFIG_FILE
fi