Shell:在for循环内创建和分配变量

时间:2020-03-05 12:05:28

标签: linux bash shell sh

我有这个shell脚本;这是一个循环,每次结果时都在变量“ a” 中设置:

declare -a names=("one" "two" "three" "four")

    for item in "${names[@]}";
    do 
     a="$(cat <<-EOF
        {
          "NAME": "${item}_ABC",
          "CHANGED": "${item}_CHANGING",
          "VERSION": "${item}_GC",
        }
    EOF
    )"
    done
    echo $a

我的目的是如何通过动态变量名称$item_MYPREFIX

更改“ a”

并置$item + _MYPREFIX

这样我的代码将是通用的,就像这样:

for item in "${names[@]}";
do 
 $item_MYPREFIX="$(cat <<-EOF
    {
          "NAME": "${item}_ABC",
          "CHANGED": "${item}_CHANGING",
          "VERSION": "${item}_GC",
    }
EOF
)"
done

并且我将能够显示每个变量:echo $one_MYPREFIXecho $two_MYPREFIX...。

当然,这不是天才的工作

建议,要遏制它?

5 个答案:

答案 0 :(得分:2)

使用关联数组。

declare -A foo

for item in "${names[@]}";
do 
 foo[$item]="{
          \"NAME\": \"${item}_ABC\",
          \"CHANGED\": \"${item}_CHANGING\",
          \"VERSION\": \"${item}_GC\"
    }"
done

答案 1 :(得分:1)

尝试一下

#!/bin/bash
for item in "${names[@]}"; do 
varname=${item}_MYPREFIX
declare $varname="
    {
          \"NAME\": \"${item}_ABC\",
          \"CHANGED\": \"${item}_CHANGING\",
          \"VERSION\": \"${item}_GC\",
    }
"
echo "${!varname}"
done

但是最好使用数组。

#!/bin/bash
declare -A array
names=("one" "two" "three" "four")
for item in "${names[@]}"; do 
indexname=${item}_MYPREFIX
array[$indexname]="
    {
          \"NAME\": \"${item}_ABC\",
          \"CHANGED\": \"${item}_CHANGING\",
          \"VERSION\": \"${item}_GC\",
    }
"
echo "${array[$indexname]}"
done

答案 2 :(得分:0)

不需要heredocs,请尝试此。

#!/usr/bin/env bash

declare -a names=("one" "two" "three" "four")
declare -a prefix=(foo bar baz more)

for item in "${!names[@]}"; do
   array+=("${prefix[$item]} = {
      "NAME": "${names[$item]}_ABC",
      "CHANGED": "${names[$item]}_CHANGING",
      "VERSION": "${names[$item]}_GC",
    }"
   )
done

printf '%s\n' "${array[@]}"

输出

foo = {
      NAME: one_ABC,
      CHANGED: one_CHANGING,
      VERSION: one_GC,
    }
bar = {
      NAME: two_ABC,
      CHANGED: two_CHANGING,
      VERSION: two_GC,
    }
baz = {
      NAME: three_ABC,
      CHANGED: three_CHANGING,
      VERSION: three_GC,
    }
more = {
      NAME: four_ABC,
      CHANGED: four_CHANGING,
      VERSION: four_GC,
    }

答案 3 :(得分:0)

这实际上不是最佳实践,但是您可以(以bash方式)这样做:

p.id

我相信那里唯一的bashism(除了数组的存在,但是有几个shell有数组)是$ cat a.sh #!/bin/bash declare -a names=("one" "two" "three" "four") for item in "${names[@]}"; do eval "read -d '' ${item}_MYPREFIX" << EOF { "NAME": "${item}_ABC", "CHANGED": "${item}_CHANGING", "VERSION": "${item}_GC", } EOF done for item in "${names[@]}"; do k="${item}_MYPREFIX" echo "$k = ${!k}" done $ ./a.sh one_MYPREFIX = { "NAME": "one_ABC", "CHANGED": "one_CHANGING", "VERSION": "one_GC", } two_MYPREFIX = { "NAME": "two_ABC", "CHANGED": "two_CHANGING", "VERSION": "two_GC", } three_MYPREFIX = { "NAME": "three_ABC", "CHANGED": "three_CHANGING", "VERSION": "three_GC", } four_MYPREFIX = { "NAME": "four_ABC", "CHANGED": "four_CHANGING", "VERSION": "four_GC", } 间接的用法,但这只是用于输出,并不是真正必要的。但是,由于您使用的是支持数组的外壳,因此您可能根本不这样做。而不是创建一个名为“ two_MYPREFIX”的变量,您应该创建一个数组并将该值存储在索引2中,或者使用一个关联数组并以索引“ two”存储。这比使用${!...}更干净。

答案 4 :(得分:0)

没有eval,没有关联数组且使用模板的Bash解决方案:

#!/usr/bin/env bash

declare -a names=("one" "two" "three" "four")

read -r -d '' template <<'EOF'
{
    "NAME": "%q_ABC",
    "CHANGED": "%q_CHANGING",
    "VERSION": "%q_GC"
}
EOF

for item in "${names[@]}"; do
  # shellcheck disable=SC2059 # format with a template variable
  printf -v "${item}_MYPREFIX" "$template" "$item" "$item" "$item" 
done

# Dump variables for debug
IFS=$'\n' read -r -d '' -a k < <(printf '%s_MYPREFIX\n' "${names[@]}")
typeset -p "${k[@]}"

输出:

declare -- one_MYPREFIX="{
    \"NAME\": \"one_ABC\",
    \"CHANGED\": \"one_CHANGING\",
    \"VERSION\": \"one_GC\"
}"
declare -- two_MYPREFIX="{
    \"NAME\": \"two_ABC\",
    \"CHANGED\": \"two_CHANGING\",
    \"VERSION\": \"two_GC\"
}"
declare -- three_MYPREFIX="{
    \"NAME\": \"three_ABC\",
    \"CHANGED\": \"three_CHANGING\",
    \"VERSION\": \"three_GC\"
}"
declare -- four_MYPREFIX="{
    \"NAME\": \"four_ABC\",
    \"CHANGED\": \"four_CHANGING\",
    \"VERSION\": \"four_GC\"
}"