Reputation: 113
I am trying to edit a postgres configuration file using script
I would like to search if
listen_addresses = '*'
already present or not. If already present, do nothing and if the exact string is not present, add the entry using following rule
If there is any configuration line with listen_addresses
but with any other value that '*' exists, then I need to comment the line with a comment
Commented out on DD-MM-YYYY by XYZ
and then add a new line
listen_addresses = '*'
followed by a comment
Added on DD-MM-YYYY by XYZ
What I tried is some thing like this:
sed -i 's/^#?listen_addresses .*/listen_addresses = '*'/' /etc/postgresql/9.3/main/postgresql.conf
But that do not help adding the comments and will insert only
listen_addresses = *
due to missing escape characters.
I could not figure out how to accomplish this change.
Upvotes: 1
Views: 1650
Reputation: 28963
If it doesn't exist, you want to start by commenting it out? Sounds like a contradiction, but eh.
Any line starting with listen_addresses with any other value - Matching "[this] not followed by [that]" needs a negative lookahead, which sed
regexes don't support.
sed
processes line by line, which makes it difficult to search the entire file and then decide whether to make changes.
This will be much easier if you either:
a) Comment out every listen_address =
line, regardless of whether it's correct, then always add a new one to the end of the file:
sed -i "s/^\(listen_addresses .*\)/# Commented out by Name YYYY-MM-DD \1/" postgresql.conf
echo "listen_addresses = '*'" >> postgresql.conf
That would get annoying if you run this script regularly, as the file would grow and grow forever.
or
b) Use tools other than sed
. But you haven't said you have any other tools available. Grep would make it easier, Perl even easier. But sticking with sed (and bash), what about a variation on the above:
# Comment out every listen_address line:
sed -i "s/^\(listen_addresses .*\)/#\1 Commented out by Name YYYY-MM-DD/" postgresql.conf
# Try to uncomment a correct one:
sed -i "s/^#\(listen_addresses = '\*'\).*/\1/" postgresql.conf
# Check if the correct one exists, and if it doesn't, add it:
if ! sed -n -e "/^listen_addresses = '\*'/!ba;Q0;:a;\$Q1" postgresql.conf ; then
echo "listen_addresses = '*'" >> postgresql.conf
fi
OK, the constrained sed only was fun, but this is more straightforward logic and adds the new line just after a commented one.
#!/bin/env bash
if grep -q "^listen_addresses = '\*'" postgresql.conf ; then
echo "Correct listen_addresses found, doing nothing"
exit
fi
if ! grep -q "^listen_addresses =.*" postgresql.conf ; then
echo "No listen_addresses found, adding one at the end"
echo "listen_addresses = '*'" >> postgresql.conf
exit
fi
if grep -q "^listen_addresses =.*" postgresql.conf ; then
echo "Wrong listen_addresses found, commenting them out"
sed -i "s/^\(listen_addresses.*\)/#\1 Commented out by Name YYYY-MM-DD/" postgresql.conf
echo "Adding correct one"
sed -i "/^#listen_addresses/a listen_addresses = '\*'" postgresql.conf
fi
Upvotes: 5
Reputation: 784958
In shell you cannot nest single quote inside single quotes. Also use double quote for using shell variables in sed.
Try this sed:
comment="commented on $(date)"
sed -i "s~^#?listen_addresses .*~listen_addresses = '*'\n$comment~" /etc/postgresql/9.3/main/postgresql.conf
Upvotes: 2