【问题标题】:Create associative array from grep output从 grep 输出创建关联数组
【发布时间】:2018-11-09 02:57:07
【问题描述】:

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

这是我的 grep 输出:

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

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

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

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

【问题讨论】:

  • 可能吗?是的。你试过什么?
  • 我正在寻找要使用的正确语法。但是我很难理解这些命令。现在我在看这个语法:declare -A DeviceId while read -r val key; do DeviceId[${key#HardwareSerialNumber}]=$val done

标签: arrays bash associative-array


【解决方案1】:

要么将您的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

【讨论】:

  • 很高兴它有帮助。 Bash 通过其 参数扩展 具有强大的字符串处理能力。它们是内置的,因此在使用中没有子进程开销。祝你的脚本好运。
【解决方案2】:

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

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:我在大卫的回答和网络上的示例中看到了declare -A;我使用了declare -a,因为这是我的bash 版本想要的(我使用的是Mac)。因此,请注意可能存在差异。

【讨论】:

  • 请注意,您可能想将if [[ "$lineA" == "" ]]; then break; fi 移动到紧跟在read lineA &lt; "${1:-/dev/stdin}" 之后,因此如果读取命中EOF,您不要尝试read lineB &lt; "${1:-/dev/stdin}"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 2018-10-04
  • 2020-12-04
  • 2014-08-17
  • 2014-06-29
相关资源
最近更新 更多