我对bash脚本感到困惑。

我有以下代码:

function grep_search() {
    magic_way_to_define_magic_variable_$1=`ls | tail -1`
    echo $magic_variable_$1
}

我希望能够创建一个变量名,其中包含命令的第一个参数,并承载例如ls的最后一行的值。

为了说明我想要的:

$ ls | tail -1
stack-overflow.txt

$ grep_search() open_box
stack-overflow.txt

那么,我应该如何定义/声明$magic_way_to_define_magic_variable_$1,我应该如何在脚本中调用它?

我已经试过eval, ${…}, \$${...},但我还是很困惑。


当前回答

接吻的方法:

a=1
c="bam"
let "$c$a"=4
echo $bam1

结果4

其他回答

使用声明

没有必要像其他答案一样使用前缀,也没有数组。只使用声明、双引号和参数展开。

我经常使用下面的技巧来解析包含1到n个参数的参数列表,格式为key=value otherkey=othervalue etc=etc,例如:

# brace expansion just to exemplify
for variable in {one=foo,two=bar,ninja=tip}
do
  declare "${variable%=*}=${variable#*=}"
done
echo $one $two $ninja 
# foo bar tip

但是展开argv列表就像

for v in "$@"; do declare "${v%=*}=${v#*=}"; done

额外的建议

# parse argv's leading key=value parameters
for v in "$@"; do
  case "$v" in ?*=?*) declare "${v%=*}=${v#*=}";; *) break;; esac
done
# consume argv's leading key=value parameters
while test $# -gt 0; do
  case "$1" in ?*=?*) declare "${1%=*}=${1#*=}";; *) break;; esac
  shift
done

对于zsh(更新的mac os版本),您应该使用

real_var="holaaaa"
aux_var="real_var"
echo ${(P)aux_var}
holaaaa

而不是“!”

尽管这是一个老问题,但我在获取动态变量名时仍然遇到了一些困难,同时避免使用eval (evil)命令。

用declare -n解决了这个问题,它创建了一个动态值的引用,这在CI/CD进程中特别有用,其中CI/CD服务所需的秘密名称直到运行时才知道。方法如下:

# Bash v4.3+
# -----------------------------------------------------------
# Secerts in CI/CD service, injected as environment variables
# AWS_ACCESS_KEY_ID_DEV, AWS_SECRET_ACCESS_KEY_DEV
# AWS_ACCESS_KEY_ID_STG, AWS_SECRET_ACCESS_KEY_STG
# -----------------------------------------------------------
# Environment variables injected by CI/CD service
# BRANCH_NAME="DEV"
# -----------------------------------------------------------
declare -n _AWS_ACCESS_KEY_ID_REF=AWS_ACCESS_KEY_ID_${BRANCH_NAME}
declare -n _AWS_SECRET_ACCESS_KEY_REF=AWS_SECRET_ACCESS_KEY_${BRANCH_NAME}

export AWS_ACCESS_KEY_ID=${_AWS_ACCESS_KEY_ID_REF}
export AWS_SECRET_ACCESS_KEY=${_AWS_SECRET_ACCESS_KEY_REF}

echo $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
aws s3 ls

虽然我认为声明-n仍然是最好的方法,但还有另一种没有人提到的方法,在CI/CD中非常有用

function dynamic(){
  export a_$1="bla"
}

dynamic 2
echo $a_2

此函数不支持空格,因此动态“2 3”将返回错误。

使用关联数组,命令名作为键。

# Requires bash 4, though
declare -A magic_variable=()

function grep_search() {
    magic_variable[$1]=$( ls | tail -1 )
    echo ${magic_variable[$1]}
}

如果你不能使用关联数组(例如,你必须支持bash 3),你可以使用declare来创建动态变量名:

declare "magic_variable_$1=$(ls | tail -1)"

并使用间接参数展开来访问该值。

var="magic_variable_$1"
echo "${!var}"

参见BashFAQ:间接-计算间接/引用变量。