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_[@]}"\)
}