I have an application where I want the user to be able to enter ip addresses that are saved to a conf file. The addresses need to be checked to ensure they are valid ip addresses (xxx.xxx.xxx.xxx) Given that this is a user set persistent value running on a user application (ie. not root), the conf file must reside in a user folder. I have chosen the user home directory (Raspbian).
The conf file test sample looks like this:
interface=eth0
ip_address=172.30.21.40
routers=172.30.21.1
domain_name_server_1=199.85.126.30
damaim_name_server_2=8.8.8.8
If the user saves a valid ip_address, I want to read and store this in a variable . If the user saves an invalid ip_address, then I want to read and discard the ip address and return an empty string.
I have looked at range of options to do this.
I looked at using source, but I found this requires the conf to be executable. That would add the risk of a user injecting executable code into the conf file.
I think I should be able to read, check and store the ip_address value in a one line sed command, but I just can't get it to work.
The test script is:
!/bin/bash
conf_file='/home/user/ip.conf'
v1="$(sed -n 's/\b(?:ip_address=)(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b/\1/p' $conf_file)"
echo "The ip address is : $v1"
exit
To break this down into parts:
\b(?:ip_address=) # match the string "ip_address=" starting with a word separator \b
(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))
^ ^
# This section checks the format and number range of the ip address. This is made up of three
# groups that are all contained with a set of brackets (marked with ^) to create a group 1 with
# the whole ip address. This is what I want to capture. This ends with a word separator \b
/\1/p # This is the substitution section where I specify group 1 and print to save to $v1.
When I run this command I get the error
sed: -e expression #1, char 110: invalid reference \1 on `s' command's RHS
When I enter:
\b(?:ip_address=)(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b
into the online regex tester it works without error. It identifies the full ip address as group 1.
The sed command doesn't seem to recognise the back reference \1 and I can't figure out what I am doing wrong.
Edit
I tried a simple command:
v1="$(sed -n -E 's/^\s*(interface=)(.*)\b/\2/p' $conf_file)"
This only worked correctly with the -E option added. This is based on an answer found here. I can't find any documentation on -E but it appears to enable extended regular expressions.