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)
.