views:

671

answers:

5

I'm writing a bash script to modify a config file which contains a bunch of key, value pairs. How can i read the key and find the value and possibly modify it?

A: 

Suppose your config file is in below format:
------------------------------------------------------
CONFIG_NUM=4
CONFIG_NUM2=5
CONFIG_DEBUG=n
------------------------------------------------------

In your bash script, you can use:
------------------------------------------------------
CONFIG_FILE=your_config_file
. $CONFIG_FILE

if [ $CONFIG_DEBUG == "y" ]; then
......
else
......
fi
------------------------------------------------------
$CONFIG_NUM, $CONFIG_NUM2, $CONFIG_DEBUG is what you need.

After your read the values, write it back will be easy:
echo "CONFIG_DEBUG=y" >> $CONFIG_FILE

datasunny
That won't replace the value, just add it again at the bottom, it's completely dependent on the config file being a valid bash script, and... wow, what if there's something malicious in the config file?
Jefromi
+2  A: 

A wild stab in the dark for modifying a single value:

sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE

assuming that the target key and replacement value don't contain any special regex characters, and that your key-value separator is "=".

Jefromi
-c seems to be invalid in my environment. When I get rid of -c, it works. Thanks.
CKeven
The `-c` option tells sed to copy the file when it shuffles it (instead of renaming) - it prevents changing ownership and messing with read-only files. One of those habits I've picked up to save myself from stupid mistakes (especially with `find ... | xargs sed -i`).
Jefromi
Did I really get two downvotes for this answer? Not only did I manage to guess what the OP wanted, it's short and efficient. Anyone care to explain?
Jefromi
+2  A: 

in general it's easy to extract the info with grep and cut:


cat "$FILE" | grep "^${KEY}${DELIMITER}" | cut -f2- -d"$DELIMITER"

to update you could do something like this:


mv "$FILE" "$FILE.bak"
cat "$FILE.bak" | grep -v "^${KEY}${DELIMITER}" > "$FILE"
echo "${KEY}${DELIMITER}${NEWVALUE}" >> "$FILE"

this would not maintain the order of the key-value pairs obviously. add error checking to make sure you don't lose your data.

JPL
if you run out of disk space or if for whatever reason you cannot create `FILE` then your solution will leave `FILE` missing (one would have to manually rename `FILE.bak` back to `FILE` to recover.)
vladr
you bet. that's why i wrote 'add error checking' etc. :)
JPL
A: 

Assuming that you have a file of key=value pairs, potentially with spaces around the =, you can delete, modify in-place or append key-value pairs at will using awk even if the keys or values contain special regex sequences:

# Using awk to delete, modify or append keys
# In case of an error the original configuration file is left intact
# Also leaves a timestamped backup copy (omit the cp -p if none is required)
CONFIG_FILE=file.conf
cp -p "$CONFIG_FILE" "$CONFIG_FILE.orig.`date \"+%Y%m%d_%H%M%S\"`" &&
awk -F '[ \t]*=[ \t]*' '$1=="keytodelete" { next } $1=="keytomodify" { print "keytomodify=newvalue" ; next } { print } END { print "keytoappend=value" }' "$CONFIG_FILE" >"$CONFIG_FILE~" &&
mv "$CONFIG_FILE~" "$CONFIG_FILE" ||
echo "an error has occurred (permissions? disk space?)"
vladr
A: 
sed "/^$old/s/\(.[^=]*\)\([ \t]*=[ \t]*\)\(.[^=]*\)/\1\2$replace/" configfile