Populating multiple arrays with output from a loop.

huangapple go评论78阅读模式
英文:

Populating multiple arrays with output from a loop

问题

Here's the translated portion of your text:

  1. 如何将循环的结果存储在数组中?
  2. 给定以下的 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

  1. 我正在努力将输出(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]}"

  1. ...但没有成功。var1 var4 是空的。
  2. 我认为我可能错过了一个非常简单的技巧。任何帮助都将不胜感激!
  3. 编辑:
  4. 明确一下,当仅使用

for str in ${types[@]}; do
retrieveSensors | grep $str
done

  1. 该脚本在屏幕上正确打印出 4 个预期的传感器类型列表,如电压传感器、电流等。
  2. 来自 `$endpoint/states` JSON 输出如下:
  3. ```json
  4. {
  5. "entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
  6. "state": "50.53842",
  7. "attributes": {
  8. "state_class": "total_increasing",
  9. "unit_of_measurement": "kWh",
  10. "device_class": "energy",
  11. "friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
  12. },
  13. "last_changed": "2023-05-25T15:36:59.985247+00:00",
  14. "last_updated": "2023-05-25T15:36:59.985247+00:00",
  15. "context": {
  16. "id": "01H19RWRAHXP5P2ZCG85W8Y131",
  17. "parent_id": null,
  18. "user_id": null
  19. }
  20. }

有数百个传感器,我需要对其进行筛选。

从这个超长的 JSON 列表中,我需要匹配以下条件的 entity_id

  • 以 "sensor.shelly" 开头
  • 在 types=("active_power" "_voltage" "_current" "total_active_energy") 中

我现在意识到我不需要将适当的 entity_id 过滤后存储在多个数组中 - 一个数组就足够了!👍

  1. Is there anything else you would like to know or clarify in this context?
  2. <details>
  3. <summary>英文:</summary>
  4. How to store results of loops in arrays?
  5. 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

  1. I&#39;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]}"

  1. ...to no avail. var1..var4 are empty.
  2. I assume there&#39;s a hella easy trick I&#39;m missing here. Asssistance would be greatly appreciated!
  3. EDIT:
  4. to be clear, when using only

for str in ${types[@]}; do
retrieveSensors | grep $str
done

  1. The script correctly prints to screen the 4x expected lists of specified sensor types, voltage sensors, current, etc.
  2. 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
}
},

  1. There are hundreds of sensors, which I need to filter.
  2. From this crazy long JSON list, I need the `entity_id`s matching:
  3. startswith(&quot;sensor.shelly&quot;)
  4. AND
  5. types=(&quot;active_power&quot; &quot;_voltage&quot; &quot;_current&quot; &quot;total_active_energy&quot;)
  6. 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! &#128077;
  7. </details>
  8. # 答案1
  9. **得分**: 3
  10. 首先,让我们将这个问题分解成更小的部分。例如,在您的实际代码中,您可能会有:
  11. ```shell
  12. retrieveSensors() {
  13. curl \
  14. -H "Authorization: Bearer $token" \
  15. -H "Content-Type: application/json" \
  16. "$endpoint/states"
  17. }

但在这个示例中,我将使用以下代码:

  1. retrieveSensors() {
  2. cat <<'EOF'
  3. [
  4. {
  5. "entity_id": "sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy",
  6. "state": "50.53842",
  7. "attributes": {
  8. "state_class": "total_increasing",
  9. "unit_of_measurement": "kWh",
  10. "device_class": "energy",
  11. "friendly_name": "shellypro3em-c8f09e8968b0 phase c total active energy"
  12. },
  13. "last_changed": "2023-05-25T15:36:59.985247+00:00",
  14. "last_updated": "2023-05-25T15:36:59.985247+00:00",
  15. "context": {
  16. "id": "01H19RWRAHXP5P2ZCG85W8Y131",
  17. "parent_id": null,
  18. "user_id": null
  19. }
  20. }
  21. ]
  22. EOF
  23. }

在以上任意一个示例中,我们可以运行以下代码:

  1. readarray -t matchingSensorIds < <(
  2. retrieveSensors | jq -r '
  3. .[]
  4. | .entity_id
  5. | select(
  6. test(
  7. "sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
  8. )
  9. )
  10. '
  11. )

或者,对于与古老的4.0版本之前的bash兼容性:

  1. IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
  2. retrieveSensors | jq -r '
  3. .[]
  4. | .entity_id
  5. | select(
  6. test(
  7. "sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
  8. )
  9. )
  10. ' && printf '
    IFS=$'\n' read -r -d '' -a matchingSensorIds < <(
  11.   retrieveSensors | jq -r '
  12.     .[]
  13.     | .entity_id
  14.     | select(
  15.         test(
  16.           "sensor.shelly.*(active_power|_voltage|_current|total_active_energy)"
  17.         )
  18.       )
  19.   ' && printf '\0'
  20. )
  21. '
  22. )

这将创建一个类似以下的数组:

  1. $ declare -p matchingSensorIds
  2. declare -a matchingSensorIds=("sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy")

其中仅包含以 sensor.shelly 开头并包含 active_power_voltage_currenttotal_active_energy 的传感器ID。

英文:

First, let's break this down into smaller pieces. For example, in your real code you might have:

  1. retrieveSensors() {
  2. curl \
  3. -H &quot;Authorization: Bearer $token&quot; \
  4. -H &quot;Content-Type: application/json&quot; \
  5. &quot;$endpoint/states&quot;
  6. }

but in this example, I'm instead going to use:

  1. retrieveSensors() {
  2. cat &lt;&lt;&#39;EOF&#39;
  3. [
  4. {
  5. &quot;entity_id&quot;: &quot;sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy&quot;,
  6. &quot;state&quot;: &quot;50.53842&quot;,
  7. &quot;attributes&quot;: {
  8. &quot;state_class&quot;: &quot;total_increasing&quot;,
  9. &quot;unit_of_measurement&quot;: &quot;kWh&quot;,
  10. &quot;device_class&quot;: &quot;energy&quot;,
  11. &quot;friendly_name&quot;: &quot;shellypro3em-c8f09e8968b0 phase c total active energy&quot;
  12. },
  13. &quot;last_changed&quot;: &quot;2023-05-25T15:36:59.985247+00:00&quot;,
  14. &quot;last_updated&quot;: &quot;2023-05-25T15:36:59.985247+00:00&quot;,
  15. &quot;context&quot;: {
  16. &quot;id&quot;: &quot;01H19RWRAHXP5P2ZCG85W8Y131&quot;,
  17. &quot;parent_id&quot;: null,
  18. &quot;user_id&quot;: null
  19. }
  20. }
  21. ]
  22. EOF
  23. }

Given one of the above, we can run:

  1. readarray -t matchingSensorIds &lt; &lt;(
  2. retrieveSensors | jq -r &#39;
  3. .[]
  4. | .entity_id
  5. | select(
  6. test(
  7. &quot;sensor.shelly.*(active_power|_voltage|_current|total_active_energy)&quot;
  8. )
  9. )
  10. &#39;
  11. )

...or, for compatibility with ancient pre-4.0 bash releases:

  1. IFS=$&#39;\n&#39; read -r -d &#39;&#39; -a matchingSensorIds &lt; &lt;(
  2. retrieveSensors | jq -r &#39;
  3. .[]
  4. | .entity_id
  5. | select(
  6. test(
  7. &quot;sensor.shelly.*(active_power|_voltage|_current|total_active_energy)&quot;
  8. )
  9. )
  10. &#39; &amp;&amp; printf &#39;
    IFS=$&#39;\n&#39; read -r -d &#39;&#39; -a matchingSensorIds &lt; &lt;(
  11. retrieveSensors | jq -r &#39;
  12. .[]
  13. | .entity_id
  14. | select(
  15. test(
  16. &quot;sensor.shelly.*(active_power|_voltage|_current|total_active_energy)&quot;
  17. )
  18. )
  19. &#39; &amp;&amp; printf &#39;\0&#39;
  20. )
  21. &#39;
  22. )

...which will create an array like the following:

  1. $ declare -p matchingSensorIds
  2. declare -a matchingSensorIds=([0]=&quot;sensor.shellypro3em_c8f09e8968b0_phase_c_total_active_energy&quot;)

containing only those sensor ids that start with sensor.shelly and contain active_power, _voltage, _current, or total_active_energy.

huangapple
  • 本文由 发表于 2023年5月25日 22:46:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76333570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定