bash 在函数内声明全局变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9871458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:51:05  来源:igfitidea点击:

Declaring global variable inside a function

bashshellscope

提问by Leonid99

What I want to do is following. Inside a function, I need to assign a value to a variable, whose name is taken from another variable. In other words:

我想做的是跟随。在函数内部,我需要为一个变量赋值,该变量的名称取自另一个变量。换句话说:

func() {  
  #  
  # Here happens something that ultimately makes $arg="var_name"
  # 
  declare -g ${arg}=5
}

func

echo ${var_name}; # Prints out "5"

The code snippet above works great in bash 4.2. However, in bash before 4.2, declaredoesn't have the -goption. Everything I found at google says that to define the global variable inside a function, I should just use the var=valuesyntax, but unfortunately varitself depends on another variable. ${arg}=5doesn't work, either. (It says -bash: var_name=5: command not found.

上面的代码片段在 bash 4.2 中效果很好。但是,在 bash 4.2 之前,declare没有-g选项。我在 google 找到的所有内容都说要在函数内定义全局变量,我应该只使用var=value语法,但不幸的是,var它本身取决于另一个变量。${arg}=5也不行。(它说-bash: var_name=5: command not found

For the curious, the reason for all this is that this function actually creates global variables from the script parameters, i.e. running script --arg1=valautomatically creates variable named arg1with value val. Saves tons of a boilerplate code.

出于好奇,这一切的原因是这个函数实际上从脚本参数创建了全局变量,即运行script --arg1=val自动创建以arg1value命名的变量val。节省大量样板代码。

采纳答案by minopret

You could construct your var=value as a string and evaluate it using the bash builtin command eval.

您可以将 var=value 构造为字符串并使用 bash 内置命令对其进行评估eval

回答by kipibenkipod

declareinside a function doesn't work as expected. I needed read-only global variables declared in a function. I tried this inside a function but it didn't work:

declare函数内部无法按预期工作。我需要在函数中声明的只读全局变量。我在一个函数中尝试过这个,但没有用:

declare -r MY_VAR=1

But this didn't work. Using the readonlycommand did:

但这没有用。使用readonly命令做了:

func() {
    readonly MY_VAR=1
}
func
echo $MY_VAR
MY_VAR=2

This will print 1 and give the error "MY_VAR: readonly variable" for the second assignment.

这将打印 1 并为第二个赋值给出错误“MY_VAR:只读变量”。

回答by William Pursell

Since this is tagged shell, it is important to note that declareis a valid keyword only in a limited set of shells, so whether it supports -g is moot. To do this sort of thing in a generic Bourne shell, you can just use eval:

由于 this 被标记为shell,重要的是要注意它declare仅在有限的一组 shell中是一个有效的关键字,因此它是否支持 -g 是没有实际意义的。要在通用 Bourne shell 中执行此类操作,您只需使用 eval:

eval ${arg}=5

回答by gniourf_gniourf

I think you need the printfbuiltin with its -vswitch:

我认为你需要printf内置的-v开关:

func() {
    printf -v "$var" '5'
}
var=var_name
func
echo "$var_name"

will output 5.

将输出5.

回答by Beorn Harris

Using "eval" (or any direct assignment) can give you headaches with special characters (or issues with value injection etc).

使用“eval”(或任何直接赋值)会让您对特殊字符(或值注入等问题)感到头疼。

I've had great success just using "read"

我只使用“阅读”就取得了巨大的成功

$ function assign_global() {
>   local arg=""
>   IFS="" read -d "" $arg <<<""
>}
$ assign_global MYVAR 23
echo $MYVAR
23
$ assign_global MYVAR "\"'"
"'

回答by Zach

If you want something a little less hackish, try using exportin place of declare -g. It has the added benefit of being an environment variable now.

如果你想要一些不那么骇人听闻的东西,请尝试使用export代替declare -g. 它现在具有作为环境变量的额外好处。

func() {  
#  
# Here happens something that ultimately makes $arg="var_name"
# 
export ${arg}=5
}

func

echo ${var_name}; # Prints out "5"

Unfortunately, this still does not work for arrays.

不幸的是,这仍然不适用于数组。

回答by tomy

In Bash for declaring array variables inside a function definition you can use the localcommand in combination with the evalcommand like in the following example:

在 Bash 中,为了在函数定义中声明数组变量,您可以将该local命令与eval以下示例中的命令结合使用:

#!/bin/bash
function test
{
    local -g 
    local array=( AA BB 'C C' DD)
    eval ='("${array[@]}")'
}
test VAR
echo VAR=${VAR[@]:1:2}

the output will be:

输出将是:

$./test.sh
VAR=BB C C

works with: GNU bash, Version 4.4.18

适用于:GNU bash,版本 4.4.18

回答by Ekeyme Mo

Maybe your could use the following functions to dynamically assign your global variable in bash(< 4.2). If > 2 args passed, then the value will be array type. E.G

也许您可以使用以下函数在 bash(< 4.2) 中动态分配全局变量。如果 > 2 args 传递,则该值将是数组类型。例如

_set2globals variable_name arg1 [arg2] [arg3] [...]

Source:

来源:

# dynamically set $variable_name()=$values(...) to globals scope
function _set2globals()
{
    if (( $# < 2 )); then
        printf "$FUNCNAME: expect at least 2 argument, but %d you given.\n" $# >&2
        exit 1
    fi
    local ___pattern_='^[_a-zA-Z][_0-9a-zA-Z]*$'
    if [[ !  =~ $___pattern_ ]]; then
        printf "$FUNCNAME: invalid variable name: %s.\n" "" >&2
        exit 1
    fi
    local __variable__name__=
    shift
    local ___v_
    local ___values_=()
    while (($# > 0)); do
        ___v_=\'${1//"'"/"'\''"}\'
        ___values_=("${___values_[@]}" "$___v_") # push to array
        shift
    done

    eval $__variable__name__=\("${___values_[@]}"\)
}

回答by ASG

Eval will work with Array variables...I just had to single quote the local Array variable inside the eval statement.

Eval 将使用 Array 变量...我只需要在 eval 语句中用单引号引用局部 Array 变量。

The below reads in a file (1st arg) a line at a time and then copies it to the variable name passed to the 2nd arg of the get_file.

下面一次读入一个文件(第一个参数)一行,然后将其复制到传递给 get_file 的第二个参数的变量名中。

get_file () {
  declare -a Array=();
  while read line; do
    Array=("${Array[@]}" "($line)")
  done < 
  eval ='("${Array[@]}")'
  unset Array
}

declare -a my_array=();
get_file /etc/myfile.conf my_array
echo ${#my_array[@]}