7

I need to put the output of a command into an associative array.

For example:

dig mx +short google.com

Will return:

20 alt1.aspmx.l.google.com.
40 alt3.aspmx.l.google.com.
50 alt4.aspmx.l.google.com.
10 aspmx.l.google.com.
30 alt2.aspmx.l.google.com.

How can I create an associative array using the priorities (10,20,...) as the key and the record (aspmx.l.google.com.) as the value?

1
  • If any of the existing answers solves your problem, please consider accepting it via the checkmark. Thank you!
    – Jeff Schaller
    Apr 25, 2017 at 10:40

4 Answers 4

9

Here is one way to read that data into a bash associative array:

Code:

#!/usr/bin/env bash
declare -A hosts
while IFS=" " read -r priority host ; do
  hosts["$priority"]="$host"
done < <(dig mx +short google.com)    

for priority in "${!hosts[@]}" ; do
  echo "$priority -> ${hosts[$priority]}"
done

Output:

20 -> alt1.aspmx.l.google.com.
10 -> aspmx.l.google.com.
50 -> alt4.aspmx.l.google.com.
40 -> alt3.aspmx.l.google.com.
30 -> alt2.aspmx.l.google.com.
0
2
declare -A mx
eval $(dig mx +short google.com | sed "s/'//g; s/^/mx[/; s/ /]='/; s/$/';/")

First declare an associative array named mx, then execute dig and used sed to convert the output into associative array assignments, then eval that into the current shell. The sed command strips all single quotes, then wraps the variable assignment in, using single-quotes to quote the value.

1

First of all, I think Stephen Rauch's solution (alongside chepner's comment) is great. But when it comes to associative arrays, I almost always use dictionaries in Python, not because I don't like Bash, but because they are (in my opinion) easier to work with in a higher level language.

Below is an example of usage in Python.

#!/usr/bin/env python3

import subprocess
import os
import json

digDict = {}
tmpOut = open("tmpOut", "w")
output = subprocess.call(['dig', 'mx', '+short', 'google.com'], stdout=tmpOut)

# Fill the dictionary with the values we want
with open("tmpOut") as infile:
    for line in infile:
        digDict[line.split()[0]] = line.split()[1]

os.remove("tmpOut")

# Sort the dictionary by key
print("Sorted dictionary:")
for key in sorted(digDict):
    print(key + " -> " + digDict[key])

# Get a specific value based on key
print("Access value associated with key '10' (digDict[\"10\"]):")
print(digDict["10"])

# "Pretty print" the dictionary in json format
print("json format:")
print(json.dumps(digDict, sort_keys=True, indent=4))

# Saved the dictionary to file in json format
with open("digDict.json", "w") as fp:
    json.dump(digDict, fp, sort_keys=True, indent=4)

exit(0)

Execution:

./myDig.py 
Sorted dictionary:
10 -> aspmx.l.google.com.
20 -> alt1.aspmx.l.google.com.
30 -> alt2.aspmx.l.google.com.
40 -> alt3.aspmx.l.google.com.
50 -> alt4.aspmx.l.google.com.
Access value associated with key '10' (digDict["10"]):
aspmx.l.google.com.
json format:
{
    "10": "aspmx.l.google.com.",
    "20": "alt1.aspmx.l.google.com.",
    "30": "alt2.aspmx.l.google.com.",
    "40": "alt3.aspmx.l.google.com.",
    "50": "alt4.aspmx.l.google.com."
}

cat digDict.json:

{
    "10": "aspmx.l.google.com.",
    "20": "alt1.aspmx.l.google.com.",
    "30": "alt2.aspmx.l.google.com.",
    "40": "alt3.aspmx.l.google.com.",
    "50": "alt4.aspmx.l.google.com."
}

Again; the solution above in Bash is great (and upvoted by me). This is just another example in Python, nothing more.

0

You can use the internal field separator to separate the input into lines

 IFS="\n" read -ra ADDR <<< "$IN"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .