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:

array[123456789101]=devid1234
array[11213141516]=devid5678

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

728x90

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.

#!/bin/bash

declare -A array
declare -i n=0
arridx=

while read -r label value; do       # read 2 fields
    if [ "$n" -eq 0 ]
    then 
        arridx="${value:1}"         # strip 1st and lst 2 chars
        arridx="${arridx:0:(-2)}"   # save in arridx (array index)
        ((n++))                     # increment toggle
    else
        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
    fi
done

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

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 parsegrep2array.sh
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:

so.input

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

so.sh

#!/bin/bash

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"

    hwsn=$lineA
    hwsn=${hwsn//HardwareSerialNumber/}
    hwsn=${hwsn//\"/}
    hwsn=${hwsn//:/}
    hwsn=${hwsn//,/}
    echo $hwsn
    # some checking could be done here to test that the value is numeric

    devid=$lineB
    devid=${devid//DeviceId/}
    devid=${devid//\"/}
    devid=${devid//:/}
    devid=${devid//,/}
    echo $devid
    # some checking could be done here to make sure the value is valid

    # populate the array
    hardwareInfo[$hwsn]=$devid

done

# spacer, for readability of the output
echo

# 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 | ./so.sh

"HardwareSerialNumber": "123456789101",
"DeviceId": "devid1234",
123456789101
devid1234
"HardwareSerialNumber": "111213141516",
"DeviceId": "devid5678",
111213141516
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 | ./so.sh

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