在函数内声明全局变量

时间:2022-10-08 00:41:13

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, declare doesn't have the -g option. Everything I found at google says that to define the global variable inside a function, I should just use the var=value syntax, but unfortunately var itself depends on another variable. ${arg}=5 doesn't work, either. (It says -bash: var_name=5: command not found.

上面的代码片段在bash 4.2中运行良好。但是,在4.2之前的bash中,declare没有-g选项。我在google上发现的一切都说要在函数内定义全局变量,我应该使用var = value语法,但遗憾的是var本身依赖于另一个变量。 $ {arg} = 5也不起作用。 (它说-bash:var_name = 5:找不到命令。

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=val automatically creates variable named arg1 with value val. Saves tons of a boilerplate code.

对于好奇,所有这一切的原因是该函数实际上从脚本参数创建全局变量,即运行脚本--arg1 = val自动创建名为arg1且值为val的变量。节省了大量的样板代码。

9 个解决方案

#1


2  

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

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

#2


14  

declare inside 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 -r MY_VAR=1

But this didn't work. Using the readonly command 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:readonly variable”。

#3


7  

Since this is tagged shell, it is important to note that declare is 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:

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

eval ${arg}=5

#4


3  

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="$1"
>   IFS="" read -d "" $arg <<<"$2"
>}
$ assign_global MYVAR 23
echo $MYVAR
23
$ assign_global MYVAR "\"'"
"'

#5


3  

I think you need the printf builtin with its -v switch:

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

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

will output 5.

将输出5。

#6


2  

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

如果你想要一些不那么hackish的东西,尝试使用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.

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

#7


1  

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

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

#!/bin/bash
function test
{
    local -g $1
    local array=( AA BB 'C C' DD)
    eval ${1}='("${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

#8


0  

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

Eval将使用数组变量...我只需要在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.

下面一次读取一行文件(1st arg),然后将其复制到传递给get_file第二个arg的变量名。

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

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

#9


0  

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($1)=$values($2...) 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 [[ ! $1 =~ $___pattern_ ]]; then
        printf "$FUNCNAME: invalid variable name: %s.\n" "$1" >&2
        exit 1
    fi
    local __variable__name__=$1
    shift
    local ___v_
    local ___values_=()
    while (($# > 0)); do
        ___v_=\'${1//"'"/"'\''"}\'
        ___values_=("${___values_[@]}" "$___v_") # push to array
        shift
    done

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

#1


2  

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

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

#2


14  

declare inside 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 -r MY_VAR=1

But this didn't work. Using the readonly command 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:readonly variable”。

#3


7  

Since this is tagged shell, it is important to note that declare is 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:

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

eval ${arg}=5

#4


3  

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="$1"
>   IFS="" read -d "" $arg <<<"$2"
>}
$ assign_global MYVAR 23
echo $MYVAR
23
$ assign_global MYVAR "\"'"
"'

#5


3  

I think you need the printf builtin with its -v switch:

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

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

will output 5.

将输出5。

#6


2  

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

如果你想要一些不那么hackish的东西,尝试使用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.

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

#7


1  

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

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

#!/bin/bash
function test
{
    local -g $1
    local array=( AA BB 'C C' DD)
    eval ${1}='("${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

#8


0  

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

Eval将使用数组变量...我只需要在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.

下面一次读取一行文件(1st arg),然后将其复制到传递给get_file第二个arg的变量名。

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

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

#9


0  

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($1)=$values($2...) 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 [[ ! $1 =~ $___pattern_ ]]; then
        printf "$FUNCNAME: invalid variable name: %s.\n" "$1" >&2
        exit 1
    fi
    local __variable__name__=$1
    shift
    local ___v_
    local ___values_=()
    while (($# > 0)); do
        ___v_=\'${1//"'"/"'\''"}\'
        ___values_=("${___values_[@]}" "$___v_") # push to array
        shift
    done

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