You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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]}"

问题原因

  1. 直接使用output+=$(...)会把所有命令输出拼接成数组的第一个元素,而非按行拆分为多个独立元素——因为$(...)的返回值是单个字符串,默认不会自动分词为数组元素。
  2. 循环中每次都调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 22:10:36