Create associative array from grep output

I have a grep output and I'm trying to make an associative array from the output that I get.

Here is my grep output:

"HardwareSerialNumber": "123456789101",
"DeviceId": "devid1234",
"HardwareSerialNumber": "111213141516",
"DeviceId": "devid5678",

I want to use that output to define an associative array, like this:


Is that possible? I'm new at making arrays. I hope someone could help me in my problem.


2 Answers Create associative array from grep output

Either pipe your grep output to a helper script with a while loop containing a simple "0/1" toggle to read two lines taking the last field of each to fill your array, e.g.


declare -A array
declare -i n=0

while read -r label value; do       # read 2 fields
    if [ "$n" -eq 0 ]
        arridx="${value:1}"         # strip 1st and lst 2 chars
        arridx="${arridx:0:(-2)}"   # save in arridx (array index)
        ((n++))                     # increment toggle
        arrval="${value:1}"         # strip 1st and lst 2 chars
        arrval="${arrval:0:(-2)}"   # save in arrval (array value)
        array[$arridx]="$arrval"    # assign to associative array
        n=0                         # zero toggle

for i in ${!array[@]}; do           # output array
    echo "array[$i]  ${array[$i]}"

Or you can use process substitution containing the grep command within the script to do the same thing, e.g.

done < <( your grep command )

You can also add a check under the else clause that if [[ $label =~ DeviceId ]] to validate you are on the right line and catch any variation in the grep output content.

Example Input

$ cat dat/grepout.txt
"HardwareSerialNumber": "123456789101",
"DeviceId": "devid1234",
"HardwareSerialNumber": "111213141516",
"DeviceId": "devid5678",

Example Use/Output

$ cat dat/grepout.txt | bash
array[123456789101]  devid1234
array[111213141516]  devid5678

4 months ago

Parsing out the values is easy, and once you have them you can certainly use those values to build up an array. The trickiest part comes from the fact that you need to combine input from separate lines. Here is one approach; note that this script is verbose on purpose, to show what's going on; once you see what's happening, you can eliminate most of the output:


"HardwareSerialNumber": "123456789101",
"DeviceId": "devid1234",
"HardwareSerialNumber": "111213141516",
"DeviceId": "devid5678",


declare -a hardwareInfo

while [[ 1 ]]; do
    # read in two lines of input
    # if either line is the last one, we don't have enough input to proceed

    read lineA < "${1:-/dev/stdin}"
    # if EOF or empty line, exit
    if [[ "$lineA" == "" ]]; then break; fi

    read lineB < "${1:-/dev/stdin}"
    # if EOF or empty line, exit
    if [[ "$lineB" == "" ]]; then break; fi

    echo "$lineA"
    echo "$lineB"

    echo $hwsn
    # some checking could be done here to test that the value is numeric

    echo $devid
    # some checking could be done here to make sure the value is valid

    # populate the array


# spacer, for readability of the output

# display the array; in your script, you would do something different and useful
for key in "${!hardwareInfo[@]}"; do echo $key --- ${hardwareInfo[$key]}; done

cat so.input | ./

"HardwareSerialNumber": "123456789101",
"DeviceId": "devid1234",
"HardwareSerialNumber": "111213141516",
"DeviceId": "devid5678",

111213141516 --- devid5678
123456789101 --- devid1234

I created the input file so.input just for convenience. You would probably pipe your grep output into the bash script, like so:

grep-command | ./

EDIT #1: There are lots of choices for parsing out the key and value from the strings fed in by grep; the answer from @David C. Rankin shows another way. The best way depends on what you can rely on about the content and structure of the grep output.

There are also several choices for reading two separate lines that are related to each other; David's "toggle" approach is also good, and commonly used; I considered it myself, before going with "read two lines and stop if either is blank".

EDIT #2: I see declare -A in David's answer and in examples on the web; I used declare -a because that's what my version of bash wants (I'm using a Mac). So, just be aware that there can be differences.

4 months ago