如何将函数的结果分配给变量?[复制]

How do I assign the result of a function to a variable? [duplicate]

提问人:itsLOKO 提问时间:6/4/2022 更新时间:6/4/2022 访问量:136

问:

我制作了以下函数来计算数组的最大值:

MaxArray(){
aux ="$1"
for n in "$@"
do
    [ "$n" -gt "$aux" ] && aux="$n"
done
return $aux
}

我尝试将回车更改为回声“$aux”,看看它是否正确计算了值并且有效。对于具有以下值的数组:(1, 10, 152, 0, 3),我尝试返回并调用函数,如下所示:

value=$( MaxArray ${array[@]} )
echo "value is $value"

但是调用函数后$value是空的。 如何正确地将函数的返回分配给$value?

Linux Bash 函数 shell 参数传递

评论

0赞 Gordon Davisson 6/4/2022
我在这里对类似问题的回答可能会有所帮助......
0赞 pjh 6/4/2022
另请参阅如何从 Bash 函数返回字符串值和 BashFAQ/084(如何从函数返回字符串(或大数或负数)?“return”只能让我给出一个从 0 到 255 的数字。

答:

3赞 user000001 6/4/2022 #1

取代

return $aux

echo "$aux"

命令替换捕获标准输出,而不是退出状态。

顺便说一句,变量赋值不应在等号之前或之后有空格,赋值应为

aux="$1"
2赞 Fravadona 6/4/2022 #2

在 shell 中,传递值是通过输出完成的,而不是通过返回代码完成的:

#!/bin/bash

MaxArray() {
    local n aux="$1"
    for n in "$@"
    do
        (( n > aux )) && aux=$n
    done
    echo "$aux"
}

value=$( MaxArray "${array[@]}" )
3赞 Renaud Pacalet 6/4/2022 #3

您不会返回用于返回退出状态的值。通过将值发送到标准输出 (, ...) 来返回值如果你的 bash 足够新,一个避免子 shell 的更好解决方案是将变量名称作为函数参数传递,并使用命名引用 ():returnechoprintflocal -n var=name

MaxArray(){
  local -n tmp="$1"
  local -i n
  tmp="$2"
  shift 2
  for n in "$@"; do
    [ "$n" -gt "$tmp" ] && tmp="$n"
  done
}

然后:

$ unset value
$ MaxArray value 1 2 3 4 5 4 3 2 1
$ echo $value
5

请注意,如果值存储在索引数组中,则可以使用相同的原则来传递其名称而不是其内容:

$ MaxArray(){
  local -n tmp="$1"
  local -n arr="$2"
  local -i n
  tmp="${arr[0]}"
  for n in "${arr[@]}"; do
    [ "$n" -gt "$tmp" ] && tmp="$n"
  done
}

$ declare -a values=( 1 2 3 4 5 4 3 2 1 )
$ unset value
$ MaxArray value values
$ echo $value
5
2赞 2 revsLéa Gris #4

函数有多种方法可以返回值:

第一种方法是在全局变量中提供结果。此方法也适用于所有 POSIX shell 变体:

#!/bin/sh

# Here we use the global ret variable to get the result of the function
ret=

max() {
  ret=$1
  shift
  for n
  do
    [ "$n" -gt "$ret" ] && ret=$n
  done
}

max 1 8 2 7 42 23 17

printf 'The maximum of %s is %s\n' '1 8 2 7 42 23 17' "$ret"

另一种常用方法也是 POSIX shell 友好的。它涉及将结果流式传输到(打印它),并在调用函数时将其捕获到变量中。这涉及到一个子 shell,因此在循环中应避免:stdout

#!/bin/sh

max() {
  gtst=$1
  shift
  for n
  do
    [ "$n" -gt "$gtst" ] && gtst=$n
  done
  # Print the result
  printf %s "$gtst"
}

# Capture the printout of max into the ret variable
ret=$(max 1 8 2 7 42 23 17)

printf 'The maximum of %s is %s\n' '1 8 2 7 42 23 17' "$ret"

第三种方法涉及通过变量名称间接寻址变量,使用:eval

#!/bin/sh

max() {
  # Get the name of the return variable
  ret_name=$1
  shift
  gtst=$1
  shift
  for n
  do
    [ "$n" -gt "$gtst" ] && gtst=$n
  done
  # Evaluate expression to assign returned value to provided variable name
  eval "$ret_name=$gtst"
}

# will get the result into the variable ret
max ret 1 8 2 7 42 23 17

# shellcheck disable=SC2154 # dynamically referrenced ret
printf 'The maximum of %s is %s\n' '1 8 2 7 42 23 17' "$ret"

最后,此方法使用 nameref 变量,这些变量仅适用于 4.2 版开始的 Bash:

#!/bin/bash

max() {
  # Get the name of the return variable into a nameref variable
  local -n gtst=$1
  local -i n
  shift
  gtst=$1
  shift
  for n
  do
    declare -p gtst
    [ "$n" -gt "$gtst" ] && gtst=$n
  done
}

# will get the result into the variable ret
declare -i ret
max ret 1 8 2 7 42 23 17

# shellcheck disable=SC2154 # dynamically referrenced ret
printf 'The maximum of %s is %s\n' '1 8 2 7 42 23 17' "$ret"

所有版本的输出相同:

The maximum of 1 8 2 7 42 23 17 is 42