Bash变量范围问题

时间:2017-11-23 01:46:34

标签: bash jq

我正在努力了解以下错误的原因以及如何解决它。

我有这段代码:

set_filters() {
  json=$1
  filters='"Name=instance-state-name,Values=running,stopped"'
  echo $json | jq -r '. | keys[]' | \
    while read tag ; do
      value=$(echo "$json" | jq -r ".[\"$tag\"]")
      filters="$filters \"Name=tag:${tag},Values=${value}\""
    done
  echo $filters
}

set_filters '{"Name": "*FOO*", "Cost Center": "XX111"}'

我期待的输出:

"Name=instance-state-name,Values=running,stopped" "Name=tag:Cost Center,Values=XX111" "Name=tag:Name,Values=*FOO*"

我得到的输出:

"Name=instance-state-name,Values=running,stopped" 

如果我插入echo语句以帮助调试:

set_filters() {
  json=$1
  filters='"Name=instance-state-name,Values=running,stopped"'
  echo $json | jq -r '. | keys[]' | \
    while read tag ; do
      value=$(echo "$json" | jq -r ".[\"$tag\"]")
      filters="$filters \"Name=tag:${tag},Values=${value}\""
      echo "FILTERS INSIDE LOOP: $filters"
    done
  echo "FILTERS OUTSIDE LOOP: $filters"
}

我得到的输出是:

FILTERS INSIDE LOOP: "Name=instance-state-name,Values=running,stopped" "Name=tag:Cost Center,Values=XX111"
FILTERS INSIDE LOOP: "Name=instance-state-name,Values=running,stopped" "Name=tag:Cost Center,Values=XX111" "Name=tag:Name,Values=*FOO*"
FILTERS OUTSIDE LOOP: "Name=instance-state-name,Values=running,stopped"

我无法解释这种行为。在Bash以外的语言中,我会假设变量$filters的变量范围问题,但我认为范围基本上是全局的。

我在Red Hat Enterprise Linux 6.8上使用JQ版本1.3和Bash版本4.1.2。

1 个答案:

答案 0 :(得分:2)

Bash在子shell中执行循环,如果它们是管道的一部分。例如,请参阅BashFAQ/024和" Bash Script: While-Loop Subshell Dilemma"。

可能的解决方法是使用流程替换:

while read tag; do
  ...
done < <(jq -r '. | keys[]' <<< "$1")