我正在使用 NUT 服务器进行 UPS 监控项目。我的目标是制作一个 shell 脚本,该脚本发送一个命令并作为响应接收来自 UPS 的状态和其他参数。
例如
#!/bin/bash
status='upsc myups' # command to get the status of UPS
sleep 1
exit 0
这对我来说工作正常,但如果我将“状态”声明为数组,则来自 ups 的响应将存储为单个元素
IE
#!/bin/bash
declare -a status #declare status as array
# command
status=$(upsc myups) or status=`upsc myups`
#number of array elements
echo ${status[@]}
exit 0
状态数组中的元素数量:
1
终端输出/数组输出
echo ${#status[1]}
如果我回显该数组,输出如下所示:
Init SSL without certificate database
battery.capacity: 9.00 battery.charge: 90 battery.charge.low: 20
battery.charge.restart: 0 battery.energysave: no battery.protection: yes
ups.shutdown: enabled ups.start.auto: yes ups.start.battery: yes
ups.start.reboot: yes ups.status: OL CHRG ups.test.interval: 604800
ups.test.result: Done and passed ups.timer.shutdown: -1
ups.timer.start: -1
ups.type: offline / line interactive ups.vendorid: 0463
因为整个输出保存在“status”数组的单个元素中。我在单独使用所有参数来记录日志时遇到了麻烦。
期望的输出:
battery.capacity: 9.00
battery.charge: 90
battery.charge.low: 20
battery.charge.restart: 0
battery.energysave: no
battery.protection: yes
如何将每个参数分成数组或变量的单个元素?
请帮忙
谢谢
答案1
您从中返回的数据的upsc
形式为keyword: value
,每行一个。您可以通过它来sed
获取 form [keyword]="value"
,然后使用它来初始化关联数组:
declare -A status="($(upsc myups | sed 's/\(.*\): \(.*\)/ [\1]="\2"/'))"
现在您可以获取任何关键字的值,例如echo "${status[device.model]}"
。您可以循环遍历所有键和值并执行您想要的操作:
for key in "${!status[@]}"
do echo "$key: ${status[$key]}"
done
请注意,如果您引用您的价值观,
status="$(upsc myups)"
echo "${status[@]}"
您仍然会得到一个值,但每个值都将位于一个新行上,如您所需的输出所示。
答案2
您可能会考虑:
upsc myups | grep -oP 'battery(\.\w+)+: \S+'
您的主要需要是引用您的变量:
status=$(upsc myups)
echo "$status"
答案3
您可以使用readarray
bash 内置命令:
readarray status < <(upsc myups)
答案4
最简单的解决方案是将数组(即括在括号中)而不是字符串分配给$status
.
还将 IFS 设置为换行符 ( \n
),以便将每一行(而不是每个单词)放入单独的数组元素中:
$ IFS=$'\n' status=( $(upsc myups 2>/dev/null | grep '^battery\.') )
$ printf "%s\n" "${status[@]}"
battery.capacity: 9.00
battery.charge: 90
battery.charge.low: 20
battery.charge.restart: 0
battery.energysave: no
battery.protection: yes
$ declare -p status # reformatted slightly for readability.
declare -a status='([0]="battery.capacity: 9.00" [1]="battery.charge: 90"
[2]="battery.charge.low: 20" [3]="battery.charge.restart: 0"
[4]="battery.energysave: no" [5]="battery.protection: yes")'
PS:如果您要对这些upsc
值进行更多处理,我强烈建议使用perl
orawk
或python
代替bash
- 它们都比bash
单独使用更适合编写复杂的文本处理工具。