0

I have made the following function to calculate the maximum value of an array:

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

I tried changing return to echo "$aux" to see if it calculated the value correctly and it worked. With an array with the following values: (1, 10, 152, 0, 3), I tried return and called the function like this:

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

But $value is empty after calling the function. How can I assign the return of the function to $value correctly?

2

4 Answers 4

3

Replace

return $aux

with

echo "$aux"

Command substitution captures the standard output, not the exit status.

As an aside, variable assignments should not have spaces before or after the equal sign, the assignment should be

aux="$1"
Sign up to request clarification or add additional context in comments.

Comments

3

You don't return a value with return which is used to return an exit status. You return a value by sending it to the standard output (echo, printf...) If your bash is recent enough a better solution that avoids a sub-shell is to pass the variable name as a function argument and use a named reference (local -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
}

Then:

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

Note that if your values are stored in an indexed array you can use the same principle to pass its name instead of its content:

$ 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

Comments

2

In the shell, passing values is done through the output, not the return code:

#!/bin/bash

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

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

Comments

2

There are multiple methods for functions to return values:

1st method is to provide the result in a global variable. This method also works for all POSIX-shell variants:

#!/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"

The other common method is also POSIX-shell friendly. It involves streaming the result to stdout (printing it), and capturing it into a variable when calling the function. This involves a sub-shell and is to be avoided in a loop for this reason:

#!/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"

The third method involves addressing a variable indirectly by its name, using 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"

Finally this method use nameref variables which are only available to Bash starting at version 4.2:

#!/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"

Same output for all versions:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.