Home > Software design >  Filter ip returned and name server into a dictionary. bash
Filter ip returned and name server into a dictionary. bash

Time:09-16

I have a file like so: Example1:

haproxy-1
google_b 127.0.0.1
haproxy-2
google_b 127.0.0.1
haproxy-3
google_b 127.0.0.2

The file might have multiple values for the ips like so: Example2:

haproxy-1
google_b 127.0.0.1
google_b 127.0.0.2
haproxy-2
google_b 127.0.0.1
google_b 127.0.0.2
haproxy-3
google_b 127.0.0.1
google_b 127.0.0.2

The only variabe i can go by is the google_b variable. Ips and name servers are unknown but can be sorted via awk regex. My goal is to take each ip the servers returned and put it into a dictionary.

The dictionary key needs to be the IP returned (if multiple ips then the multiple ips). The dictionary value needs to be the server that returned that answer.

In general i want a dictionary to look like so:

For example 1:

haproxy_results=( ["127.0.0.1"]="haproxy-1 haproxy-2" ["127.0.0.2"]="haproxy-3")

For example 2:

haproxy_results=( ["127.0.0.1"]="haproxy-1 haproxy-2 haproxy-3" ["127.0.0.2"]="haproxy-1 haproxy-2 haproxy-3")

Example 3:

haproxy-3
google_b 127.0.0.1
google_b 127.0.0.2
haproxy-4
Can't find backend

How i do this now is i get the values for each server seperatly, format them to get the returned ips and the server and just add it to the dictionary like so:

haproxy-server is the haproxy-1 or haproxy-2 etc...

haproxy_ip_returned is the ips 127.0.0.1 127.0.0.2 etc...

haproxy_results =([$haproxy_ip_returned] =$haproxy-server)

This is bad because i use ansible to get the data and ssh to each server seperatly causes the code to be very slow.

Any ideas on how to do this?

CodePudding user response:

$ eval declare -A haproxy_results=( $(
    awk -v tgt='google_b' '
        NF == 1 {
            srvr = $0
        }
        (NF == 2) && ($1 == tgt) {
            srvrs[$2] = ($2 in srvrs ? srvrs[$2] OFS : "") srvr
        }
        END {
            for (ip in srvrs) {
                printf "%s[\"%s\"]=\"%s\"", sep, ip, srvrs[ip]
                sep = OFS
            }
            print ""
        }
    ' file
) )

$ declare -p haproxy_results
declare -A haproxy_results=([127.0.0.2]="haproxy-1 haproxy-2 haproxy-3" [127.0.0.1]="haproxy-1 haproxy-2 haproxy-3" )

Warning: that use of eval will expose the contents of your file to the shell for interpretation and so variables like $PWD and commands like $(ls) in the input will be expanded so only use it if you're sure such constructs cannot occur in your input. More robustly but slightly less efficiently you can do:

$ declare -A haproxy_results

$ while read -r ip srvrs; do
    haproxy_results["$ip"]="$srvrs"
done < <(
    awk -v tgt='google_b' '
        NF == 1 {
            srvr = $0
        }
        (NF == 2) && ($1 == tgt) {
            srvrs[$2] = ($2 in srvrs ? srvrs[$2] OFS : "") srvr
        }
        END {
            for (ip in srvrs) {
                print ip, srvrs[ip]
            }
        }
    ' file
)

$ declare -p haproxy_results
declare -A haproxy_results=([127.0.0.2]="haproxy-1 haproxy-2 haproxy-3" [127.0.0.1]="haproxy-1 haproxy-2 haproxy-3" )

The above assumes that in your real data you have IP addresses for input that doesn't start with google_b and you want to ignore those. If that's not the case then get rid of -v tgt='google_b' and && ($1 == tgt).

  • Related