I am trying to do something that should be simple and routine. I want to search the file /etc/dhcpcd.conf and change an uncommented static ip address assigned to eth0. The sample test file is shown here:
interface eth0
# test variants of comments
#static ip_address=192.168.21.40/24
# static ip_address=192.168.21.40/24
#static ip_address=192.168.21.40/24
# static ip_address=192.168.21.40/24
#the line to match and change
static ip_address=123.223.122.005/24
I attempted to implement a solution here: here’s a much-less-cryptic way of doing it in awk answered by Scott - Слава Україні
I chose the AWK solution because it is easy to read however, I have not been able to modify the answer to work for me. I haven't used sed
or awk
before so I wrote a test script.
#!/bin/bash
# testing on a copy of the config file
conf_file="/home/user/dhcpcd.conf"
# BASH variable with fake test ip
new_ip=111.222.123.234
cat "$conf_file" | awk $'
/interface / { matched=0 }
/interface eth0/ { matched=1 }
matched { gsub( "^\\s*static ip_address=•*" , "static ip_address=111.222.123.234" ) }
{ print }
'
This AWK script is to find the eth0
stanza, then find static ip_address=
any text.
and replace this with static ip_address=111.222.123.234
. The exception is for #
commented lines. For testing I have hard coded the test new ip into the AWK script. I want to use the variable $new_ip.
Initially had a problem with the gsub function. The •*
intended to match any text caused issues because I began using .*
. The manual says gsub uses the character •
and not a full-stop.
without actually highlighting the need to use Alt-7
. That took me a while to find but that problem is now solved.
The 1st remaining problem I now have is that the new ip is inserted in the line rather that replacing the old ip. The output is:
static ip_address=111.222.123.234123.223.122.005/24
So the regex is, or should be, matching the whole line, including the old ip to be replaced, but it isn't.
The 2nd problem I have is that I need awk
to use the bash variable new_ip
. I have looked and searched but I cannot find an answer that works.
I think this should work:
cat /home/mimir/dhcpcd.conf | awk -v sip=$new_ip $'
/interface / { matched=0 }
/interface eth0/ { matched=1 }
matched { gsub( "^[:blank:]*static ip_address=•*" , "static ip_address=sip" ) }
{ print }
'
but it doesn't. The output was
static ip_address=sip123.223.122.005/24
so awk didn't recognise sip
as a variable. I am doing something wrong, but I can't see it. It shouldn't be so difficult to do something so simple.
Any help would be much appreciated.
EDIT No.2: For the benefit of those landing here looking for a solution, this is my working test script:
#!/bin/bash
# Test reading and setting of the ip address in /etc/dhcpcd.conf using AWK
# source /etc/dhcpcd.conf which always includes the lines:
# interface eth0
# static ip_address=www.xxx.yyy.zzz
# copy of config file for testing
cfg_file="/home/user/dhcpcd.conf"
# fake test ip
new_ip="114.113.112.111"
awk -i inplace -v sip=$new_ip $'
/interface / { matched=0 }
/interface eth0/ { matched=1 }
matched { gsub( "^[[:blank:]]*static ip_address=.*" , "static ip_address="sip ) }
{ print }
' $cfg_file
exit
This is now working because of a combination of advice received below in the comments. This is an answer, but it is not my answer. It works but is not perfect.
This has some limitations. For a technically better answer, see Ed Morton's answer below.