我对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, ${…}, \$${...},但我还是很困惑。


当前回答

这个也可以

my_country_code="green"
x="country"

eval z='$'my_"$x"_code
echo $z                 ## o/p: green

在你的情况下

eval final_val='$'magic_way_to_define_magic_variable_"$1"
echo $final_val

其他回答

另外一个不依赖于您使用的shell/bash版本的方法是使用envsubst。例如:

newvar=$(echo '$magic_variable_'"${dynamic_part}" | envsubst)

哇,大部分语法都很糟糕!如果你需要间接引用数组,这里有一个简单语法的解决方案:

#!/bin/bash

foo_1=(fff ddd) ;
foo_2=(ggg ccc) ;

for i in 1 2 ;
do
    eval mine=( \${foo_$i[@]} ) ;
    echo ${mine[@]}" " ;
done ;

对于更简单的用例,我推荐使用高级bash脚本编写指南中描述的语法。

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

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

dynamic 2
echo $a_2

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

我希望能够创建一个包含该命令的第一个参数的变量名

script.sh文件:

#!/usr/bin/env bash
function grep_search() {
  eval $1=$(ls | tail -1)
}

测试:

$ source script.sh
$ grep_search open_box
$ echo $open_box
script.sh

根据帮助评估:

作为shell命令执行参数。


你也可以使用Bash ${!间接展开,正如前面提到的,但是它不支持检索数组下标。


欲进一步阅读或示例,请查看BashFAQ/006关于Indirection的内容。

我们不知道有任何技巧可以在POSIX或Bourne shell中复制该功能,而不需要eval,这可能很难安全地做到。所以,考虑这是一个自担风险的使用黑客。

但是,您应该根据以下注意事项重新考虑使用间接方法。

Normally, in bash scripting, you won't need indirect references at all. Generally, people look at this for a solution when they don't understand or know about Bash Arrays or haven't fully considered other Bash features such as functions. Putting variable names or any other bash syntax inside parameters is frequently done incorrectly and in inappropriate situations to solve problems that have better solutions. It violates the separation between code and data, and as such puts you on a slippery slope toward bugs and security issues. Indirection can make your code less transparent and harder to follow.

尽管这是一个老问题,但我在获取动态变量名时仍然遇到了一些困难,同时避免使用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