使用 bash 将多个匹配项读入数组

Posted

技术标签:

【中文标题】使用 bash 将多个匹配项读入数组【英文标题】:reading multiple matches into arrays with bash 【发布时间】:2021-12-29 18:40:15 【问题描述】:

实用程序“sas2ircu”可以为连接到主机的每个硬盘驱动器输出多行。单个驱动器的输出示例如下所示:

  Enclosure #                             : 5
  Slot #                                  : 20
  SAS Address                             : 5003048-0-185f-b21c
  State                                   : Ready (RDY)

我有一个 bash 脚本,它执行 sas2ircu 命令并对输出执行以下操作:

    通过 RDY 字符串识别驱动器 将外壳的数值(即5)读入数组'enc' 将槽的数值(即20)读入另一个数组'槽'

我的代码达到了它的目的,但我想弄清楚是否可以将它组合成一行并运行 sas2ircu 命令一次而不是两次。

mapfile -t enc < <(/root/sas2ircu 0 display|grep -B3 RDY|awk '/Enclosure/print $NF')
mapfile -t slot < <(/root/sas2ircu 0 display|grep -B2 RDY|awk '/Slot/print $NF')

我已经阅读了大量关于 awk 的内容,但我对它还是很陌生,还没有想出比我所拥有的更好的东西。有什么建议吗?

【问题讨论】:

【参考方案1】:

应该能够消除grep并将awk脚本合并成一个awk脚本;一般的想法是捕获机箱和插槽数据,然后如果/当我们看到State/RDY 我们将机箱和插槽打印到标准输出:

awk '/Enclosure/enclosure=$NF/Slot/slot=$NF/State.*(RDY)/print enclosure,slot' 

我没有sas2ircu,所以我将模拟一些数据(基于 OP 的示例):

$ cat raw.dat
  Enclosure #                             : 5
  Slot #                                  : 20
  SAS Address                             : 5003048-0-185f-b21c
  State                                   : Ready (RDY)

  Enclosure #                             : 7
  Slot #                                  : 12
  SAS Address                             : 5003048-0-185f-b21c
  State                                   : Ready (RDY)

  Enclosure #                             : 9
  Slot #                                  : 23
  SAS Address                             : 5003048-0-185f-b21c
  State                                   : Off (OFF)

模拟thw sas2ircu调用:

$ cat raw.dat | awk '/Enclosure/enclosure=$NF/Slot/slot=$NF/State.*(RDY)/print enclosure,slot'
5 20
7 12

更难的部分是将这些读入 2 个单独的数组,我不知道使用单个命令执行此操作的简单方法(例如,mapfile 不提供拆分输入文件的方法跨 2 个数组)。

使用bash/while 循环的一个想法:

unset enc slot

while read -r e s
do
    enc+=( $e )
    slot+=( $s )
done < <(cat raw.dat | awk '/Enclosure/enclosure=$NF/Slot/slot=$NF/State.*(RDY)/print enclosure,slot')

这会生成:

$ typeset -p enc slot
declare -a enc=([0]="5" [1]="7")
declare -a slot=([0]="20" [1]="12")

【讨论】:

以上是关于使用 bash 将多个匹配项读入数组的主要内容,如果未能解决你的问题,请参考以下文章

将文件中的行读入Bash数组[重复]

将空格分隔的字符串读入 Bash 中的数组

使用 fortran 将文件读入数组:跳过多个标题行

检查数组项的字符串(多个单词)

php - 如何在关联数组的数组中搜索多个键/值对并返回匹配项?

如何在 MATLAB 中将多个图像读入一个数组?