从grep输出创建关联数组

时间:2018-11-09 02:57:07

标签: arrays bash associative-array

我有一个grep输出,我正在尝试从我得到的输出中创建一个关联数组。

这是我的grep输出:

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

我想使用该输出来定义关联数组,如下所示:

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

有可能吗?我是制作数组的新手。我希望有人可以帮助我解决我的问题。

2 个答案:

答案 0 :(得分:2)

通过grep循环(包含一个简单的while循环)将"0/1"的输出通过管道传递到帮助程序脚本,以读取两行以每行的最后一个字段填充数组,例如

#!/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

或者您可以在脚本中使用包含grep命令的进程替换来完成相同的操作,例如

done < <( your grep command )

您还可以在else子句下添加一个检查if [[ $label =~ DeviceId ]],以验证您是否在右边,并捕获grep输出内容中的所有变化。

示例输入

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

使用/输出示例

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

答案 1 :(得分:1)

解析这些值很容易,一旦有了它们,您当然可以使用这些值来构建一个数组。最棘手的部分来自以下事实:您需要合并来自不同行的输入。这是一种方法;请注意,该脚本是故意冗长的,以显示正在发生的事情;一旦看到发生了什么,就可以消除大部分输出:

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

为方便起见,我创建了输入文件so.input。您可能会将grep的输出通过管道传送到bash脚本中,如下所示:

grep-command | ./so.sh

编辑#1:从grep输入的字符串中解析键和值有很多选择; @David C. Rankin的回答显示了另一种方式。最好的方法取决于您对grep输出内容和结构的依赖。

还有两个读取彼此相关的独立行的选择; David的“切换”方法也很好,并且经常使用。我自己考虑过,然后继续阅读“读两行,如果其中任何一个为空白,则停止”。

编辑2:我在David的答案和网络示例中看到declare -A;我使用了declare -a,因为这就是我的bash版本所需要的(我使用的是Mac)。因此,请注意可以存在差异。