英文:
Populating multiple arrays with output from a loop
问题
Here's the translated portion of your text:
如何将循环的结果存储在数组中?
给定以下的 Bash 脚本:
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
我正在努力将输出(4 个传感器实体的列表)存储在 4 个数组中。我已尝试:
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]}"
...但没有成功。var1 到 var4 是空的。
我认为我可能错过了一个非常简单的技巧。任何帮助都将不胜感激!
编辑:
明确一下,当仅使用
for str in ${types[@]}; do
retrieveSensors | grep $str
done
该脚本在屏幕上正确打印出 4 个预期的传感器类型列表,如电压传感器、电流等。
来自 `$endpoint/states` 的 JSON 输出如下:
```json
{
"entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
"state": "50.53842",
"attributes": {
"state_class": "total_increasing",
"unit_of_measurement": "kWh",
"device_class": "energy",
"friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
},
"last_changed": "2023-05-25T15:36:59.985247+00:00",
"last_updated": "2023-05-25T15:36:59.985247+00:00",
"context": {
"id": "01H19RWRAHXP5P2ZCG85W8Y131",
"parent_id": null,
"user_id": null
}
}
有数百个传感器,我需要对其进行筛选。
从这个超长的 JSON 列表中,我需要匹配以下条件的 entity_id
:
- 以 "sensor.shelly" 开头
- 在 types=("active_power" "_voltage" "_current" "total_active_energy") 中
我现在意识到我不需要将适当的 entity_id
过滤后存储在多个数组中 - 一个数组就足够了!👍
Is there anything else you would like to know or clarify in this context?
<details>
<summary>英文:</summary>
How to store results of loops in arrays?
Given the following bash script:
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
I'm struggling to get the output (4x lists of sensor entities) stored in 4x arrays. I have tried:
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]}"
...to no avail. var1..var4 are empty.
I assume there's a hella easy trick I'm missing here. Asssistance would be greatly appreciated!
EDIT:
to be clear, when using only
for str in ${types[@]}; do
retrieveSensors | grep $str
done
The script correctly prints to screen the 4x expected lists of specified sensor types, voltage sensors, current, etc.
The JSON output from `$endpoint/states` for a given sensor is:
{
"entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
"state": "50.53842",
"attributes": {
"state_class": "total_increasing",
"unit_of_measurement": "kWh",
"device_class": "energy",
"friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
},
"last_changed": "2023-05-25T15:36:59.985247+00:00",
"last_updated": "2023-05-25T15:36:59.985247+00:00",
"context": {
"id": "01H19RWRAHXP5P2ZCG85W8Y131",
"parent_id": null,
"user_id": null
}
},
There are hundreds of sensors, which I need to filter.
From this crazy long JSON list, I need the `entity_id`s matching:
startswith("sensor.shelly")
AND
types=("active_power" "_voltage" "_current" "total_active_energy")
It has now occured to me that I do not need to store the filtered list of appropriate `entity_id`s in multiple arrays - a single array would do just fine! 👍
</details>
# 答案1
**得分**: 3
首先,让我们将这个问题分解成更小的部分。例如,在您的实际代码中,您可能会有:
```shell
retrieveSensors() {
curl \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
"$endpoint/states"
}
但在这个示例中,我将使用以下代码:
retrieveSensors() {
cat <<'EOF'
[
{
"entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
"state": "50.53842",
"attributes": {
"state_class": "total_increasing",
"unit_of_measurement": "kWh",
"device_class": "energy",
"friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
},
"last_changed": "2023-05-25T15:36:59.985247+00:00",
"last_updated": "2023-05-25T15:36:59.985247+00:00",
"context": {
"id": "01H19RWRAHXP5P2ZCG85W8Y131",
"parent_id": null,
"user_id": null
}
}
]
EOF
}
在以上任意一个示例中,我们可以运行以下代码:
readarray -t matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
'
)
或者,对于与古老的4.0版本之前的bash兼容性:
IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
' && printf 'IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
' && printf '\0'
)
'
)
这将创建一个类似以下的数组:
$ declare -p matchingSensorIds
declare -a matchingSensorIds=("sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy")
其中仅包含以 sensor.shelly
开头并包含 active_power
、_voltage
、_current
或 total_active_energy
的传感器ID。
英文:
First, let's break this down into smaller pieces. For example, in your real code you might have:
retrieveSensors() {
curl \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
"$endpoint/states"
}
but in this example, I'm instead going to use:
retrieveSensors() {
cat <<'EOF'
[
{
"entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
"state": "50.53842",
"attributes": {
"state_class": "total_increasing",
"unit_of_measurement": "kWh",
"device_class": "energy",
"friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
},
"last_changed": "2023-05-25T15:36:59.985247+00:00",
"last_updated": "2023-05-25T15:36:59.985247+00:00",
"context": {
"id": "01H19RWRAHXP5P2ZCG85W8Y131",
"parent_id": null,
"user_id": null
}
}
]
EOF
}
Given one of the above, we can run:
readarray -t matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
'
)
...or, for compatibility with ancient pre-4.0 bash releases:
IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
' && printf 'IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
retrieveSensors | jq -r '
.[]
| .entity_id
| select(
test(
"sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
)
)
' && printf '\0'
)
'
)
...which will create an array like the following:
$ declare -p matchingSensorIds
declare -a matchingSensorIds=([0]="sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy")
containing only those sensor ids that start with sensor.shelly
and contain active_power
, _voltage
, _current
, or total_active_energy
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论