字符串操作 Shell 脚本

字符串操作 Shell 脚本

我正在使用 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

您可以使用readarraybash 内置命令:

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值进行更多处理,我强烈建议使用perlorawkpython代替bash- 它们都比bash单独使用更适合编写复杂的文本处理工具。

相关内容