英文:
How to modify a global variable within a function and return a boolean in bash?
问题
I'm working with this:
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
I have a script like below:
#!/bin/bash
map2=()
result=""
f() {
tmpA=(12 34 7844);
map2=("${tmpA[@]}");
echo true;
return;
}
result=$(f)
echo result=$result : array=${map2[@]}
Which returns:
result=true : array=
if I replace result=$(f)
simply by f
it returns:
result= : array=12 34 7844
I could not find the way to modify the global array but also get the return value.
Any idea on how to achieve this?
英文:
I'm working with this:
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
I have a script like below:
#!/bin/bash
map2=()
result=""
f() {
tmpA=(12 34 7844);
map2=("${tmpA[@]}");
echo true;
return;
}
result=$(f)
echo result=$result : array=${map2[@]}
Which returns:
result=true : array=
if I replace result=$(f)
simply by f
it returns:
result= : array=12 34 7844
I could not find the way to modify the global array but also get the return value.
Any idea on how to achieve this?
答案1
得分: 3
在$( ... )
内部进行的任何环境更改在退出时都会丢失。
然而,Bash 允许通过使用 declare -n
命令以“按引用”方式更改传递的参数:
#!/bin/bash
map2=()
result=""
f() {
declare -n resultRef=$1
declare -n map2Ref=$2
local tmpA=(12 34 7844)
map2Ref=(" ${tmpA[@]} ")
map2Ref[4]=999
resultRef=true
echo during: resultRef=$resultRef : arrayRef=${map2Ref[*]} : tmpA=${tmpA[*]}
}
f result map2
echo after: resultRef=$resultRef : arrayRef=${map2Ref[*]} : tmpA=${tmpA[*]}
echo result=$result : array=${map2[*]}
以这种方式声明的变量的行为类似于 local
- 当函数返回时它们会被丢弃。
during: resultRef=true : arrayRef=12 34 7844 999 : tmpA=12 34 7844
after: resultRef= : arrayRef= : tmpA=
result=true : array=12 34 7844 999
英文:
Any environment changes made inside $( ... )
are lost when it exits.
However, bash allows a way of changing arguments passed "by reference" by using the declare -n
command:
#!/bin/bash
map2=()
result=""
f() {
declare -n resultRef=$1
declare -n map2Ref=$2
local tmpA=(12 34 7844)
map2Ref=("${tmpA[@]}")
map2Ref[4]=999
resultRef=true
echo during: resultRef=$resultRef : arrayRef=${map2Ref[*]} : tmpA=${tmpA[*]}
}
f result map2
echo after: resultRef=$resultRef : arrayRef=${map2Ref[*]} : tmpA=${tmpA[*]}
echo result=$result : array=${map2[*]}
Variables declared in this way behave like local
- they are discarded when the function returns.
during: resultRef=true : arrayRef=12 34 7844 999 : tmpA=12 34 7844
after: resultRef= : arrayRef= : tmpA=
result=true : array=12 34 7844 999
答案2
得分: 3
使用命令替代(即,$(f) 结构),你创建了一个子shell。子shell 会继承其父shell的变量,但子shell 无法修改其父shell的环境。
如果你只是调用你的函数并检查其退出代码 $?
,那么你应该能够生成你所期望的输出:
#!/bin/bash
map2=()
result="false"
my_func() {
tmpA=(12 34 7844)
map2=("${tmpA[@]}")
}
if my_func ; then
result="true"
fi
printf "result=%s : array=%s\n" "$result" "${map2[@]}"
输出:
result=true : array=12 34 7844
请注意,你可以使用 bash -x yourscript
启用xtrace以获得更多的调试输出,你还可以将你的脚本粘贴到 https://www.shellcheck.net/ 进行帮助和检查。
英文:
Using command substitution (i.e., the $(f) construct), you are creating a subshell. Subshells inherit variables from their parent shells, but a subshell cannot modify its parent shell environment.
If you just call your function and check its exit code $?
then you should be able to generate your desired output:
#!/bin/bash
map2=()
result="false"
my_func() {
tmpA=(12 34 7844)
map2=("${tmpA[@]}")
}
if my_func ; then
result="true"
fi
printf "result=%s : array=%s\n" "$result" "${map2[@]}"
Output:
result=true : array=12 34 7844
Note that you can use bash -x yourscript
to enable xtrace for more debugging output and you can paste your script into https://www.shellcheck.net/ for help as well.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论