如何在Bash函数内修改全局变量并返回布尔值?

huangapple go评论75阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年2月18日 21:41:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493732.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定