awk

awk gsub not replacing all instances of period in field


I am trying to parse some output so that eventually I can use declare to create multiple environment variables. The problem I am encountering is that the awk statement I have is not substituting all occurrences of period in the first field ($1).

The input is generated from:

etherNIC=$(nmcli --get-values NAME connection show)
nmcli connection show $etherNIC | grep -i  "ipv4.gateway\|ipv4.route" > ./ipv4settings.txt

... which looks like this:

cat ./ipv4settings.txt
ipv4.gateway:                           192.168.2.1
ipv4.routes:                            --
ipv4.route-metric:                      -1
ipv4.route-table:                       0 (unspec)

This is is the output from awk:

cat ./ipv4settings.txt | awk '{ split($0, array, ":") ; gsub( "\\.", "_", $1 ) ;  gsub( ":" , "=" , $1 ) ; print $1$2 }'
ipv4_gateway=192.168.2.1
ipv4_routes=--
ipv4_route-metric=-1
ipv4_route-table=0

The problem is that gsub( "\\.", "_", $1 ) is not replacing all occurrences of . in $1. The output I want is:

ipv4_gateway=192.168.2.1
ipv4_routes=--
ipv4_route_metric=-1
ipv4_route_table=0

In this case the second . has been correctly replaced with _.

awk --version
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0-p9, GNU MP 6.2.0)
Copyright (C) 1989, 1991-2020 Free Software Foundation.
<snip>

Edit #1

I just realized that the correct output for ipv4.route-table should be 0 (unspec) not 0.

Edit #2

As mentioned by @markp-fuso the original property names ipv4.route-metric and ipv4.route-table have only one period (.). This is why you should code while tired. Also, I'm switching my accepted answer to @markp-fuso.


Solution

  • Assumptions/understandings:

    Adding additional input line to cover a) no spaces after the :, b) chains of white space in the value, c) : in the value and d) trailing white space in the value (NOTE: don't know if b, c or d can occur so possible overkill):

    $ cat ipv4settings.txt
    ipv4.gateway:                           192.168.2.1
    ipv4.routes:                            --
    ipv4.route-metric:                      -1
    ipv4.route-table:                       0 (unspec)
    ipv4.route-stuff:0   (unspec)   leave:these:colons:alone   
    

    NOTE: there a few spaces on the end of the last line

    One awk idea

    $ cat ipv4.awk
    BEGIN { sq = "\x27" }                                  # define single quote
    
    /^ipv4[.](gateway|route)/ {                            # lines that start with ipv4.gateway or ipv4.route
    
            pos   = index($0,":")                          # find 1st ":"
            var   = substr($0,1,pos-1)                     # parse out variable name
            value = substr($0,pos+1)                       # parse out value
    
            gsub(/[.-]/,"_",var)                           # replace periods and hyphens
            gsub(/^[[:space:]]*|[[:space:]]*$/,"",value)   # trim leading/trailing white space
    
            print var "=" sq value sq                      # print new line
    }
    

    NOTE:

    Running against OP's ipv4settings.txt file:

    $ awk -f ipv4.awk ipv4settings.txt
    ipv4_gateway='192.168.2.1'
    ipv4_routes='--'
    ipv4_route_metric='-1'
    ipv4_route_table='0 (unspec)'
    ipv4_route_stuff='0   (unspec)   leave:these:colons:alone'
    

    Applying to the raw output from the nmcli call:

    $ nmcli connection show "${etherNIC}" | awk -f ipv4.awk
    ipv4_gateway='192.168.2.1'
    ipv4_routes='--'
    ipv4_route_metric='-1'
    ipv4_route_table='0 (unspec)'
    ipv4_route_stuff='0   (unspec)   leave:these:colons:alone'