如何将Bash循环的传感器筛选结果存入数组?
Bash脚本数组赋值问题解决
问题说明
现有一段Bash脚本,其中retrieveSensors函数通过curl调用API,结合jq、grep、sed筛选出以sensor.shelly开头的entity_id;循环匹配types=("active_power" "_voltage" "_current" "total_active_energy")中的关键词时,能正确输出对应传感器列表,但尝试将结果存入数组时失败,数组内元素全为空。需求是把所有符合条件的entity_id存入单个数组。
原脚本代码
types=("active_power" "_voltage" "_current" "total_active_energy") function retrieveSensors () { curl \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" \ "$endpoint/states" \ | jq '.[] | select(.entity_id | startswith("sensor.shelly"))' \ | grep entity_id \ | sed 's/"entity_id": "\(.*\)",/\1/' } for str in ${types[@]}; do retrieveSensors | grep $str done
用户尝试的代码(赋值失败)
declare -a output for str in "${types[@]}"; do output+=$(retrieveSensors | grep $str) done var1="${output[0]}" var2="${output[1]}" var3="${output[2]}" var4="${output[3]}"
问题原因
- 直接使用
output+=$(...)会把所有命令输出拼接成数组的第一个元素,而非按行拆分为多个独立元素——因为$(...)的返回值是单个字符串,默认不会自动分词为数组元素。 - 循环中每次都调用
retrieveSensors,重复发起API请求,既低效又可能触发接口限流。
解决方案
优化版脚本(高效+正确赋值数组)
types=("active_power" "_voltage" "_current" "total_active_energy") # 简化retrieveSensors:用jq直接提取entity_id并去引号,省去grep和sed function retrieveSensors () { curl \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" \ "$endpoint/states" \ | jq -r '.[] | select(.entity_id | startswith("sensor.shelly")) | .entity_id' } # 一次性获取所有符合前缀的传感器,避免重复请求API all_shelly_sensors=$(retrieveSensors) declare -a output # 遍历传感器,匹配types中的关键词并存入数组 for sensor in $all_shelly_sensors; do for type in "${types[@]}"; do if [[ $sensor == *"$type"* ]]; then output+=("$sensor") # 用括号包裹,将每个sensor作为独立数组元素添加 break # 匹配到一个类型就停止,避免重复添加 fi done done # 测试输出数组内容 echo "数组所有元素:" for idx in "${!output[@]}"; do echo "output[$idx] = ${output[$idx]}" done
更简洁的写法(用正则一次性过滤)
types=("active_power" "_voltage" "_current" "total_active_energy") function retrieveSensors () { curl \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" \ "$endpoint/states" \ | jq -r '.[] | select(.entity_id | startswith("sensor.shelly")) | .entity_id' } # 将types转为正则表达式,用|分隔多个匹配项 type_regex=$(IFS='|'; echo "${types[*]}") declare -a output # 用readarray直接将过滤结果按行存入数组 readarray -t output < <(retrieveSensors | grep -E "$type_regex") # 测试输出 echo "数组所有元素:" for idx in "${!output[@]}"; do echo "output[$idx] = ${output[$idx]}" done
关键修正点
- 简化
retrieveSensors的处理逻辑:用jq -r直接提取并输出不带引号的entity_id,省去多余的grep和sed操作。 - 一次性获取所有符合前缀的传感器数据,避免循环中重复调用API,提升效率。
- 使用
output+=("$sensor")语法:将每个传感器ID作为独立元素添加到数组,而非拼接成单个字符串。 - 第二种写法用
readarray -t直接将命令输出按行写入数组,是Bash中批量赋值数组的高效方式。
内容的提问来源于stack exchange,提问作者q20
相关产品推荐
相关产品推荐

